Re[4]: Кто что из c++0x использует. И кто на что нарвался?
От: jazzer Россия Skype: enerjazzer
Дата: 07.12.11 08:55
Оценка:
Здравствуйте, uzhas, Вы писали:

U>Здравствуйте, Коваленко Дмитрий, Вы писали:


КД>>Лично я определяю SetB(B&& b) только в довесок к нормальному "void SetB(const B& b)"

U>а для чего это надо? почему нельзя было обойтись одним методом, принимающим аргумент по значению?
U>void SetB(B b);
U>я могу себе еще такое представить, когда два метода определяются в шаблонных классах, ибо они могут работать как с movable, так и не с movable классами (хотя тут тоже есть о чем кумекать)

Потому что представь, что твой В — это тяжелый std::vector.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[5]: Кто что из c++0x использует. И кто на что нарвался?
От: uzhas Ниоткуда  
Дата: 07.12.11 09:03
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Потому что представь, что твой В — это тяжелый std::vector.

ну прямо под землю провалимся от его веса
если клиент захочет отдать объект, он передаст владение через вызов SetB(std::move(b));
если не захочет — то передаст копию SetB(b);
Re[4]: Кто что из c++0x использует. И кто на что нарвался?
От: о_О
Дата: 07.12.11 09:33
Оценка:
Здравствуйте, uzhas, Вы писали:

U>научите готовить


сомневаюсь что моё дилетантское мнение кому-то интересно, но тем не менее:

U>1) люди начинают их впихивать туда, где передача по значению была бы приемлемой (тут можете меня поучить)

class A
{
public:
  //я чего-то не понимаю или тут реально не нужно && ? ведь это ненужное ограничение на клиента
  void SetB(B&& b)
  {
    m_b = std::move(b);
  }

  B m_b;
};


т.к. && обладают другой семантикой по сравнению с обычными &, использовать && вместо чего-то не нужно. && нужно дополнять к уже имеющимся методам. что касается случая с передачей по значению, то тут лучше вообще не использовать ни замещение ни дополнение:
void SetB(const B& b);
void SetB(B&& b); //добавили. OK

//...

void SetB(B b); //удалили
void SetB(B&& b); //добавили. WRONG -- весь клиентский код переписывать

void SetB(B b);
void SetB(B&& b); //добавили. WRONG -- возможны неоднозначности


U>2) из-за того что std::move может превратить нормальный (lvalue) объект в rvalue&& не совсем ясно (холиворно) приходится имплементить move-operator=


т.к. мы можем принять временный объект, а можем переместить один объект в другой, реализация A::operator=(B&& b) должна быть следующей:
 - освобождение ресурсов A
 - перемещение ресурсов B в A

а вот как вы это реализуете, уже не имеет значения. смысл лишь в том, чтобы объект A был чист перед перемещением, а объект B после перемещения.
Re[6]: Кто что из c++0x использует. И кто на что нарвался?
От: jazzer Россия Skype: enerjazzer
Дата: 07.12.11 09:41
Оценка:
Здравствуйте, uzhas, Вы писали:

U>Здравствуйте, jazzer, Вы писали:


J>>Потому что представь, что твой В — это тяжелый std::vector.

U>ну прямо под землю провалимся от его веса
U>если клиент захочет отдать объект, он передаст владение через вызов SetB(std::move(b));
U>если не захочет — то передаст копию SetB(b);

Ну да, либо ты делаешь все на вызывающей стороне, либо на вызваемой
Обычно предпочитают делать на вызываемой, чтоб облегчить клиентский код, чтоб клиенту не надо было все время писать std::move (более того, тебе его тоже придется написать, когда будешь присваивать).
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[5]: Кто что из c++0x использует. И кто на что нарвался?
От: uzhas Ниоткуда  
Дата: 07.12.11 09:47
Оценка:
Здравствуйте, о_О, Вы писали:

о_О>т.к. && обладают другой семантикой по сравнению с обычными &, использовать && вместо чего-то не нужно. && нужно дополнять к уже имеющимся методам.

возможно, вас сбило слово "впихивать", поэтому вы подсчитали, что что-то наращивается
представим, что класс A пишется с нуля
какую сигнатуру для SetB вы порекомендуете?


U>>2) из-за того что std::move может превратить нормальный (lvalue) объект в rvalue&& не совсем ясно (холиворно) приходится имплементить move-operator=


о_О>т.к. мы можем принять временный объект, а можем переместить один объект в другой, реализация A::operator=(B&& b) должна быть следующей:

о_О>
о_О> - освобождение ресурсов A
о_О> - перемещение ресурсов B в A
о_О>

о_О>а вот как вы это реализуете, уже не имеет значения. смысл лишь в том, чтобы объект A был чист перед перемещением, а объект B после перемещения.
ваше мнение понятно и оно вполне логично, только не у всех оно укладывается в голове (в частности у меня )
из предложенных вариантов вы приняли variant 1 и посчитали неприемлемыми 2, 3
если посмотреть на реализацию подобных операторов в стандартной либе VS2010, то можно заметить прием, который реализован в variant 3, а это заставляет подумать еще
если бы std::move не превращал нормальные объекты во "временные", то можно было бы делать банальный swap (variant 2), а так как новый стандарт разрешает корежить\портить нормальные объекты, то приходится изголяться, как в variant 3, что неблаготворно сказывается на качестве кода
Re[7]: Кто что из c++0x использует. И кто на что нарвался?
От: uzhas Ниоткуда  
Дата: 07.12.11 10:01
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Ну да, либо ты делаешь все на вызывающей стороне, либо на вызваемой

казалось бы палка о двух концах, но я так не считаю
напомню о чем я говорю, чтобы мы говорили об одном и том же:
SetB(B&&) с точки зрения дизайна вносит необоснованное ограничение (невозможность подставить lvalue) ради некоторой оптимизации
SetB(B b) не имеет такого ограничения и тоже позволяет применить оптимизацию
так вот:
1) не все вектора тяжелые
2) класс чаще всего может работать как я тяжелыми так и с легкими векторами, как следствие, решение тяжелый вектор или нет вполне логично принять на клиентской стороне
3) нет такой best-practice передавать владения векторов, вектор как тип нетяжелый, тяжелым он может быть лишь в некоторых случаях в рантайме

J>Обычно предпочитают делать на вызываемой, чтоб облегчить клиентский код, чтоб клиенту не надо было все время писать std::move (более того, тебе его тоже придется написать, когда будешь присваивать).

в реальности облегчения скорее всего не будет, т.к. клиенту все равно надо будет писать std::move, если у него lvalue
весь вопрос в том, должен ли его заставить это сделать метод SetB или же предоставить клиенту выбор
если выбора нет, то передать копию клиенту придется так:
B b;
SetB(B(b));
//work with b

Re[6]: Кто что из c++0x использует. И кто на что нарвался?
От: о_О
Дата: 07.12.11 10:19
Оценка:
Здравствуйте, uzhas, Вы писали:

U>Здравствуйте, о_О, Вы писали:


о_О>>т.к. && обладают другой семантикой по сравнению с обычными &, использовать && вместо чего-то не нужно. && нужно дополнять к уже имеющимся методам.

U>возможно, вас сбило слово "впихивать", поэтому вы подсчитали, что что-то наращивается
U>представим, что класс A пишется с нуля
U>какую сигнатуру для SetB вы порекомендуете?

по значению

U>>>2) из-за того что std::move может превратить нормальный (lvalue) объект в rvalue&& не совсем ясно (холиворно) приходится имплементить move-operator=


о_О>>т.к. мы можем принять временный объект, а можем переместить один объект в другой, реализация A::operator=(B&& b) должна быть следующей:

о_О>>
о_О>> - освобождение ресурсов A
о_О>> - перемещение ресурсов B в A
о_О>>

о_О>>а вот как вы это реализуете, уже не имеет значения. смысл лишь в том, чтобы объект A был чист перед перемещением, а объект B после перемещения.
U>ваше мнение понятно и оно вполне логично, только не у всех оно укладывается в голове (в частности у меня )

почему?)

U>из предложенных вариантов вы приняли variant 1 и посчитали неприемлемыми 2, 3


вариант 2 вообще неверен, остались 1 и 3.

U>если посмотреть на реализацию подобных операторов в стандартной либе VS2010, то можно заметить прием, который реализован в variant 3, а это заставляет подумать еще


у GCC вариант 1

U>если бы std::move не превращал нормальные объекты во "временные", то можно было бы делать банальный swap (variant 2), а так как новый стандарт разрешает корежить\портить нормальные объекты, то приходится изголяться, как в variant 3, что неблаготворно сказывается на качестве кода


для простых типов возможен только вариант 1. итого 2 разные реализации == ни есть гут

и вообще. у vc++ 3й, у gcc 1й; у меня, 1й у вас 3й -- быдлан какой-то
Re[7]: Кто что из c++0x использует. И кто на что нарвался?
От: uzhas Ниоткуда  
Дата: 07.12.11 11:00
Оценка:
Здравствуйте, о_О, Вы писали:

U>>какую сигнатуру для SetB вы порекомендуете?


о_О>по значению


вот и у меня такое же мнение

U>>ваше мнение понятно и оно вполне логично, только не у всех оно укладывается в голове (в частности у меня )


о_О>почему?)


да напрягает как-то освобождать сви ресурсы
вместо того, чтобы всю деструктивную логику держать в деструкторе, мне приходится делать функцию CloseAll() и вызывать ее из деструктора и из operator=(A&&)
U>>из предложенных вариантов вы приняли variant 1 и посчитали неприемлемыми 2, 3

о_О>вариант 2 вообще неверен, остались 1 и 3.

виноват, забыл return, основная идея этого варианта в банальном swap-е

U>>если посмотреть на реализацию подобных операторов в стандартной либе VS2010, то можно заметить прием, который реализован в variant 3, а это заставляет подумать еще


о_О>у GCC вариант 1

опачки, это интересно

о_О>и вообще. у vc++ 3й, у gcc 1й; у меня, 1й у вас 3й -- быдлан какой-то

я был бы рад, если бы вариант 2 был приемлем )) уж очень он простой )))
Re[8]: Кто что из c++0x использует. И кто на что нарвался?
От: о_О
Дата: 07.12.11 11:29
Оценка:
Здравствуйте, uzhas, Вы писали:

U>Здравствуйте, о_О, Вы писали:


U>>>какую сигнатуру для SetB вы порекомендуете?


о_О>>по значению


U>вот и у меня такое же мнение


всё верно. и вы уже сами объяснили почему

U>>>из предложенных вариантов вы приняли variant 1 и посчитали неприемлемыми 2, 3

о_О>>вариант 2 вообще неверен, остались 1 и 3.
U>виноват, забыл return, основная идея этого варианта в банальном swap-е
я и не заметил про return
я когда в свой умный указатель для COM объедков прикручивал && вначале так и написал — swap(). потом подумал и понял, что fail. далее я долго маялся — как же делать — вариант 1 или 3. т.к. я помешан на читаемости кода, решил что 1

U>>>если посмотреть на реализацию подобных операторов в стандартной либе VS2010, то можно заметить прием, который реализован в variant 3, а это заставляет подумать еще


о_О>>у GCC вариант 1

U>опачки, это интересно
stl в vs 2010 кривая. вон у shared_ptr нельзя явно инстанцировать экземпляр, т.к. они вместо _Swap написали swap
вот тут если не ошибаюсь:
  void swap(_Myt&& _Right)
  {    // exchange contents with movable _Right
    _Mybase::_Swap(_STD move(_Right));
  }
Re[7]: Кто что из c++0x использует. И кто на что нарвался?
От: Masterkent  
Дата: 08.12.11 11:23
Оценка:
о_О:

о_О>вариант 2 вообще неверен, остались 1 и 3.


Вариант 2 вполне может быть верным, тут всё зависит от требований к состоянию moved from объекта в каждом конкретном случае.

Ну и неплохо было бы напомнить о существовании 4-го варианта:

A &operator=(A &&) noexcept = default;

Добиться, чтобы это сработало, во многих случаях не так уж и сложно. Заодно не нужно будет думать о реализации функции swap (std::swap вполне хватит).
Re[8]: Кто что из c++0x использует. И кто на что нарвался?
От: о_О
Дата: 08.12.11 12:42
Оценка:
Здравствуйте, Masterkent, Вы писали:

M>Ну и неплохо было бы напомнить о существовании 4-го варианта:


M>
A &operator=(A &&) noexcept = default;

M>Добиться, чтобы это сработало, во многих случаях не так уж и сложно. Заодно не нужно будет думать о реализации функции swap (std::swap вполне хватит).

каюсь, про defaulted, deleted ещё не читал
Re[8]: Кто что из c++0x использует. И кто на что нарвался?
От: uzhas Ниоткуда  
Дата: 08.12.11 12:49
Оценка:
Здравствуйте, Masterkent, Вы писали:

M>Ну и неплохо было бы напомнить о существовании 4-го варианта:


M>
A &operator=(A &&) noexcept = default;

а как нам стандарт обещает реализовать этот оператор? среди моих трех вариантов есть "стандартный" ?
Re[8]: Кто что из c++0x использует. И кто на что нарвался?
От: SleepyDrago Украина  
Дата: 08.12.11 13:32
Оценка:
Здравствуйте, Masterkent, Вы писали:

M>о_О:


о_О>>вариант 2 вообще неверен, остались 1 и 3.


M>Вариант 2 вполне может быть верным, тут всё зависит от требований к состоянию moved from объекта в каждом конкретном случае.


M>Ну и неплохо было бы напомнить о существовании 4-го варианта:


M>
A &operator=(A &&) noexcept = default;

M>Добиться, чтобы это сработало, во многих случаях не так уж и сложно. Заодно не нужно будет думать о реализации функции swap (std::swap вполне хватит).

можно у вас, как эксперта приближенного к процессу стандартизации, спросить ссылок на то какую проблему эта вся синтаксическая карусель с rvalue решила? То есть хочется понять на примере "проблема-решение" что все эти закорючки значат. Можно просто ссылки на код, можно на группы/обсуждения. Хоть что нибудь, пожалуйста.

зы я обеими ногами за #include <thread> и все что с ним связано, но пока выглядит этот новый язык как мутный головняк.
Re[9]: Кто что из c++0x использует. И кто на что нарвался?
От: Masterkent  
Дата: 08.12.11 14:32
Оценка:
uzhas:

M>>Ну и неплохо было бы напомнить о существовании 4-го варианта:


M>>
A &operator=(A &&) noexcept = default;


U>а как нам стандарт обещает реализовать этот оператор?


Через почленный move. См. 12.8/28.

U>среди моих трех вариантов есть "стандартный" ?


Я не понял вопрос.
Re[9]: Кто что из c++0x использует. И кто на что нарвался?
От: Masterkent  
Дата: 08.12.11 14:33
Оценка:
Про rvalue references можно почитать в FAQ от Страуструпа (пройти по ссылочкам, приведённым в FAQ, также не помешает).
Re[9]: Кто что из c++0x использует. И кто на что нарвался?
От: Banned by IT  
Дата: 08.12.11 20:06
Оценка:
Здравствуйте, SleepyDrago, Вы писали:

SD>можно у вас, как эксперта приближенного к процессу стандартизации, спросить ссылок на то какую проблему эта вся синтаксическая карусель с rvalue решила? То есть хочется понять на примере "проблема-решение" что все эти закорючки значат. Можно просто ссылки на код, можно на группы/обсуждения. Хоть что нибудь, пожалуйста.


Да вот хотя бы примитивный тест:

1М элементов
sort для vector<string> — 1.852954 sec, дофигища копирований
sort для vector<string>, string c поддержкой move constructor/operator — 0.532721 sec, ни одного копирования
Разница в 3.478280 раза
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Re[9]: Кто что из c++0x использует. И кто на что нарвался?
От: jazzer Россия Skype: enerjazzer
Дата: 09.12.11 07:48
Оценка:
Здравствуйте, SleepyDrago, Вы писали:

SD>можно у вас, как эксперта приближенного к процессу стандартизации, спросить ссылок на то какую проблему эта вся синтаксическая карусель с rvalue решила? То есть хочется понять на примере "проблема-решение" что все эти закорючки значат.


Там все просто.
В С++03 при присваивании или инициализации из временного объекта происходит сначала копирование всего содержимого объекта в новый, а потом разрушение временного. std::vector, например — нужно выделить память, скопировать все объекты, которые можуг быть тяжелыми сами по себе, хотя достаточно было всего лишь перекинуть указатель на буфер и обойтись вообще без выделений и копирований.
В С++11 ссылки на rvalue позволяют явно прописать, как именно перемещать содержимое из временного объекта, и компилятор будет этим способом по возможности пользоваться.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[10]: Кто что из c++0x использует. И кто на что нарвался?
От: Sir-G  
Дата: 09.12.11 07:51
Оценка:
Здравствуйте, Banned by IT, Вы писали:

BBI>1М элементов

BBI>sort для vector<string> — 1.852954 sec, дофигища копирований
BBI>sort для vector<string>, string c поддержкой move constructor/operator — 0.532721 sec, ни одного копирования
BBI>Разница в 3.478280 раза
Я может че не понимаю... Если нужна производительность сортировки массива, то
1) можно хранить указатели на объекты (в данном случае строк).
2) делать эффективный swap элементов массива, который можно реализовать и в рамках C++03.
Re[8]: Кто что из c++0x использует. И кто на что нарвался?
От: jazzer Россия Skype: enerjazzer
Дата: 09.12.11 07:51
Оценка: +1
Здравствуйте, uzhas, Вы писали:

U>Здравствуйте, jazzer, Вы писали:


J>>Ну да, либо ты делаешь все на вызывающей стороне, либо на вызваемой

U>казалось бы палка о двух концах, но я так не считаю
U>напомню о чем я говорю, чтобы мы говорили об одном и том же:
U>SetB(B&&) с точки зрения дизайна вносит необоснованное ограничение (невозможность подставить lvalue) ради некоторой оптимизации
U>SetB(B b) не имеет такого ограничения и тоже позволяет применить оптимизацию

Это ложный выбор. Правильно объявлять оба варианта: SetB(B&&) для случаев, когда аргумент — временный объект, и SetB(const B&) — для случаев, когда объект нормальный долгоживущий.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[2]: Кто что из c++0x использует. И кто на что нарвался?
От: neFormal Россия  
Дата: 09.12.11 08:02
Оценка:
Здравствуйте, Banned by IT, Вы писали:

BBI>variadic templates


а можно примеров их удобного использования? пока встречал только всякую плохочитабельную содомию..
хотя у меня был ровно один случай, где они бы пригодились..
...coding for chaos...
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.