Re[3]: Кто что из c++0x использует. И кто на что нарвался?
От: Banned by IT  
Дата: 09.12.11 10:12
Оценка:
Здравствуйте, 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 использует. И кто на что нарвался?
От: Banned by IT  
Дата: 09.12.11 10:12
Оценка:
Здравствуйте, 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 использует. И кто на что нарвался?
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 09.12.11 11:07
Оценка:
Здравствуйте, Sir-G, Вы писали:

SG>Я может че не понимаю... Если нужна производительность сортировки массива, то

SG>1) можно хранить указатели на объекты (в данном случае строк).
SG>2) делать эффективный swap элементов массива, который можно реализовать и в рамках C++03.

STL из VS2010 при перепаковке вектора использует swap, а тот использует move-операции.

Так что лучше сразу определить свой вариант swap.

Если я все правильно попутал
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[9]: Кто что из c++0x использует. И кто на что нарвался?
От: enji  
Дата: 09.12.11 13:12
Оценка:
Здравствуйте, jazzer, Вы писали:


J>Это ложный выбор. Правильно объявлять оба варианта: SetB(B&&) для случаев, когда аргумент — временный объект, и SetB(const B&) — для случаев, когда объект нормальный долгоживущий.


Ну setB — ладно. А предположим есть функция с тремя аргументами — это что, 8 перегрузок получается?
Re[9]: Кто что из c++0x использует. И кто на что нарвался?
От: uzhas Ниоткуда  
Дата: 09.12.11 13:44
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Правильно объявлять оба варианта: SetB(B&&) для случаев, когда аргумент — временный объект, и SetB(const B&) — для случаев, когда объект нормальный долгоживущий.

чем это лучше одного метода SetB(B b) ?
я вижу лишь усложнение, а где же профит? экономия на стеке?
Re[10]: Кто что из c++0x использует. И кто на что нарвался?
От: Masterkent  
Дата: 10.12.11 10:09
Оценка:
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  
Дата: 10.12.11 10:28
Оценка:
Masterkent:

M>то во втором варианте получается на одну move-операцию больше


Тут, конечно, ещё надо учитывать особенности реализации присваивания у B. Скажем, для

struct B
{
    // ...
    B(B const &x);
    B(B &&x);

    B &operator =(B const &x)
    {
        return *this = B(x);
    }
    B &operator =(B &&x);
};

при передаче в SetB lvalue типа B или const B разницы не будет.
Re[11]: Кто что из c++0x использует. И кто на что нарвался?
От: uzhas Ниоткуда  
Дата: 10.12.11 12:41
Оценка:
Здравствуйте, Masterkent, Вы писали:

M>Если имеется в виду сравнение

да, речь об этих вариантах
но мы немного уже запутали друг друга))
моя позиция следующая
//class B is movable
class 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 использует. И кто на что нарвался?
От: Masterkent  
Дата: 10.12.11 17:15
Оценка:
uzhas:

U>из предложенных трех вариантов на практике с точки зрения дизайна в подавляющем кол-ве случаев самым лучшим является вариант A1:


Насчёт подавляющего количества случаев — х.з. Но вариант годный.

U>в A2 я вижу дубликацию логики


Не такая уж страшная дубликация получается, IMHO. Тоже годный вариант.

U>в A3 я вижу необоснованное ограничение "отдай мне владение"


Такое будет хорошо только для non-copyable B.
Re[12]: Кто что из c++0x использует. И кто на что нарвался?
От: Masterkent  
Дата: 11.12.11 15:23
Оценка:
Masterkent:

M>Тут, конечно, ещё надо учитывать особенности реализации присваивания у B. Скажем, для


M>
struct B
M>{
M>    // ...
M>    B(B const &x);
M>    B(B &&x);

M>    B &operator =(B const &x)
M>    {
M>        return *this = B(x);
M>    }
M>    B &operator =(B &&x);
M>};

Вот же ж склероз — в который раз уже забыл 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()
};
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.