Здравствуйте, neFormal, Вы писали:
BBI>>variadic templates
F>а можно примеров их удобного использования? пока встречал только всякую плохочитабельную содомию.. F>хотя у меня был ровно один случай, где они бы пригодились..
У меня тоже ровно один случай: typesafe аналог CString::Format. Раньше там была уличная магия через operator comma.
Вариадики — штука специфическая, реальная необходимость в них есть только вот таких вот случаях: когда надо передать в функцию неизвестное колво параметров и разных типов.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Re[11]: Кто что из c++0x использует. И кто на что нарвался?
Здравствуйте, Sir-G, Вы писали:
BBI>>1М элементов BBI>>sort для vector<string> — 1.852954 sec, дофигища копирований BBI>>sort для vector<string>, string c поддержкой move constructor/operator — 0.532721 sec, ни одного копирования BBI>>Разница в 3.478280 раза SG>Я может че не понимаю... Если нужна производительность сортировки массива, то
Это всего лишь был наглядный пример. Есеснно этого достичь можно разными путями. Но && введено в стандарт именно для уменьшения объёмов рукопашки.
Кроме сортировки также просто ускоряется к примеру всякий container.push_back (Object (param, param, ...)); и прочие места где объект обычно передаётся как rvalue.
SG>1) можно хранить указатели на объекты (в данном случае строк).
Можно. Но с && можно хранить сами объекты, что сильно удобнее в использовании, и тем не менее тот же vector resize будет происходить в разы быстрее.
SG>2) делать эффективный swap элементов массива, который можно реализовать и в рамках C++03.
Можно. Но тогда надо переписать тонну стандартных алгоритмов чтоб они умели использовать специальный swap для твоего типа и стандартный swap для всех остальных?
А так у тебя есть где то в глубине:
template <class T> std::move (T& a, T& b)
{
T c = std::move (a);
a = std::move (b);
b = std::move (c);
}
Который в зависимости от того имеет класс move constructor/operator= или нет работает либо через copy либо через move. Сам, автоматически.
В этом и есть смысл.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Re[11]: Кто что из c++0x использует. И кто на что нарвался?
Здравствуйте, Sir-G, Вы писали:
SG>Я может че не понимаю... Если нужна производительность сортировки массива, то SG>1) можно хранить указатели на объекты (в данном случае строк). SG>2) делать эффективный swap элементов массива, который можно реализовать и в рамках C++03.
STL из VS2010 при перепаковке вектора использует swap, а тот использует move-операции.
Так что лучше сразу определить свой вариант swap.
Если я все правильно попутал
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[9]: Кто что из c++0x использует. И кто на что нарвался?
J>Это ложный выбор. Правильно объявлять оба варианта: SetB(B&&) для случаев, когда аргумент — временный объект, и SetB(const B&) — для случаев, когда объект нормальный долгоживущий.
Ну setB — ладно. А предположим есть функция с тремя аргументами — это что, 8 перегрузок получается?
Re[9]: Кто что из c++0x использует. И кто на что нарвался?
Здравствуйте, jazzer, Вы писали:
J>Правильно объявлять оба варианта: SetB(B&&) для случаев, когда аргумент — временный объект, и SetB(const B&) — для случаев, когда объект нормальный долгоживущий.
чем это лучше одного метода SetB(B b) ?
я вижу лишь усложнение, а где же профит? экономия на стеке?
Re[10]: Кто что из c++0x использует. И кто на что нарвался?
uzhas:
J>>Правильно объявлять оба варианта: SetB(B&&) для случаев, когда аргумент — временный объект, и SetB(const B&) — для случаев, когда объект нормальный долгоживущий. U>чем это лучше одного метода SetB(B b) ? U>я вижу лишь усложнение, а где же профит? экономия на стеке?
Если имеется в виду сравнение
class A
{
public:
void SetB(B const &b)
{
m_b = b;
}
void SetB(B &&b)
{
m_b = std::move(b);
}
// ...private:
B m_b;
};
с
class A
{
public:
void SetB(B b)
{
m_b = std::move(b);
}
// ...private:
B m_b;
};
то во втором варианте получается на одну move-операцию больше (в некоторых случаях она быть устранена в соответствии с 12.8/31/3). Если такая дополнительная move-операция не напрягает, то передача по значению сгодится. Напомню, что перемещение не всегда дешёвое — нередко оно сводится к копированию.
Re[11]: Кто что из c++0x использует. И кто на что нарвался?
Здравствуйте, Masterkent, Вы писали:
M>Если имеется в виду сравнение
да, речь об этих вариантах
но мы немного уже запутали друг друга))
моя позиция следующая
//class B is movableclass A1
{
B m_b;
public:
void SetB(B b)
{
m_b = std::move(b);
}
};
class A2
{
B m_b;
public:
void SetB(const B& b)
{
m_b = b;
}
void SetB(B&& b)
{
m_b = std::move(b);
}
};
class A3
{
B m_b;
public:
void SetB(B&& b)
{
m_b = std::move(b);
}
};
из предложенных трех вариантов на практике с точки зрения дизайна в подавляющем кол-ве случаев самым лучшим является вариант A1:
в A2 я вижу дубликацию логики (профит может быть в слишком специфических случаях, когда двойной move в A1 плохо сказывается на перформансе)
в A3 я вижу необоснованное ограничение "отдай мне владение", об этом я писал выше
то есть передавайте по значению — это хорошее полезное правило для легко movable сущностей, что-то типа best practice
Re[12]: Кто что из c++0x использует. И кто на что нарвался?
Вот же ж склероз — в который раз уже забыл noexcept у move-операций проставить.
struct B
{
// ...
B(B const &x);
B(B &&x) noexcept; // или хотя бы throw()
B &operator =(B const &x)
{
return *this = B(x);
}
B &operator =(B &&x) noexcept; // или хотя бы throw()
};