Re[4]: Применение std::move в Set методе класса
От: Constructor  
Дата: 09.02.18 11:55
Оценка: 2 (1)
Здравствуйте, uzhas, Вы писали:

C>>Если сделать сеттер шаблонным, можно слегка улучшить это решение:


U>ударение на слегка или улучшить ?


Как видно из вывода программы, такой подход позволяет избежать лишнего вызова move assignment operator при передаче в сеттер l-value. Также в случае наличия перегруженного assignment operator, принимающего значение некоторого постороннего типа, не будет вызван лишний converting constructor. Если в режиме компиляции без оптимизаций (например, в debug mode) отключен copy elision, то выигрыш еще более существенный. Однако в clang++ и g++, к примеру, copy elision работает и при -O0, а отключается только специальным флагом -fno-elide-constructors.

С другой стороны, такая шаблонизация увеличит время компиляции. Поэтому улучшение все-таки спорное.

Также стоит отметить, что использовать std::enable_if в данном случае необязательно. Он лишь позволяет переместить ошибку компиляции при передаче в сеттер значения неподходящего типа из кода самого сеттера в вызывающий код (error: no matching member function for call to 'setter_name' вместо error: no viable overloaded '=').
Re[6]: Применение std::move в Set методе класса
От: AlexGin Беларусь  
Дата: 09.02.18 12:18
Оценка:
Здравствуйте, rumit7, Вы писали:

R>... но почему-бы не рассмотреть еще пару вариантов, каждый по отдельности вместо предлагаемых Вами выше:


R>
R>// https://stackoverflow.com/a/14197639/8567492
R>void set(A a) { _a = std::move(a); }
R>

ИМХО передавать объект по значению, а не по ссылке (и не по указателю): не очень правильно, с точки зрения
нерационального использования стековой памяти.
Re[7]: Применение std::move в Set методе класса
От: rumit7  
Дата: 09.02.18 13:09
Оценка: 2 (1)
Здравствуйте, AlexGin, Вы писали:

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


R>>... но почему-бы не рассмотреть еще пару вариантов, каждый по отдельности вместо предлагаемых Вами выше:


R>>
R>>// https://stackoverflow.com/a/14197639/8567492
R>>void set(A a) { _a = std::move(a); }
R>>

AG>ИМХО передавать объект по значению, а не по ссылке (и не по указателю): не очень правильно, с точки зрения
AG>нерационального использования стековой памяти.

если брать во внимание copy elision, то можно с этим поспорить..

"Want Speed? Pass by Value"
https://stackoverflow.com/a/24543391/8567492
https://stackoverflow.com/a/11373695/8567492
Re[3]: Применение std::move в Set методе класса
От: MTD https://github.com/mtrempoltsev
Дата: 09.02.18 17:02
Оценка:
Здравствуйте, uzhas, Вы писали:

MTD>>Это не метод set, если нужно передать владение, то не путай людей и назови метод take


U>ещё одно название — это не очень плохо


Это не просто не плохо — это очень даже хорошо.

U>из плюсов я бы отметил возможность на уровне компиляции проверить, что ты точно что-то отдаешь. при передаче по значению такой проверки нет =\


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

U>в STL используют два подхода:


Я бы не стал приводить в пример STL — во-первых, дизайн не везде удачен, во-вторых, многие спорные моменты — следствие эволюции языка.

U>1) дублируют названия, но принимают по const& + && (см. vector::push_back) таких большинство

U>2) вводят новые имена для перемещающих (и часто конструирующих) методов (см. emplace)

Да путаница там — мое почтение.

U>в общем, не считаю, что для сеттеров имеет смысл вводить новые названия


Второй раз:

Это не метод set, если нужно передать владение, то не путай людей и назови метод take


U>насчет take: лично я в своем коде take использую для разрушающих get методов. это неконстантные get методы, которые забирают данные из объекта. если у меня есть get метод, то он константен

U>take/get — синонимы, просто я сам проставил им разные оттенки

Это уже какая-то дикая жесть пошла. Давай переведем на русский полные названия, вдруг станет ясней?

take value — взять значение
set value — установить значение, про то, что у кого-то что-то отберут речи нет
release value — освободить значение
get value — получить значение

U>set/take для меня не синонимы, поэтому мне кажется неудачной идеей называть сеттер словом take


Третий раз:

Это не метод set, если нужно передать владение, то не путай людей и назови метод take



U>а ещё я использую слово provide для геттеров, которые делают что-то умное, а не просто делают return уже готового объекта. например, ищут\вставляют в кеш или лезут в файл\сеть


Не надо давать одинаковые имена, название метода должно описывать, что он делает, readDataFromFile или receiveNetworkPacket лучше provide.

U>если надо пошариться в мапе, то я всё же использую find в имени метода


Правильно, так и надо.
Re[7]: Применение std::move в Set методе класса
От: MTD https://github.com/mtrempoltsev
Дата: 09.02.18 17:10
Оценка: +2
Здравствуйте, AlexGin, Вы писали:

AG>ИМХО передавать объект по значению, а не по ссылке (и не по указателю): не очень правильно, с точки зрения

AG>нерационального использования стековой памяти.

Это очень правильно для небольших структур (до 4 машинных слов) имеющих тривиальный конструктор и деструктор — тогда он просто будет передан через регистры без использования стека.
Re[6]: Применение std::move в Set методе класса
От: MTD https://github.com/mtrempoltsev
Дата: 09.02.18 17:16
Оценка:
Здравствуйте, rg45, Вы писали:

R>Если разобраться, для чего может понадобиться Take? Только для того, чтоб защититься от использования объекта, после того, как мы разрешили его раскурочить, применив к нему move? Ну это достаточно сомнительное желание, ИМХО, не следует адаптировать дизайн под некорректное использование.


Нет ничего сомнительного в том, чтобы писать понятные и надежные программы.
Re[4]: Применение std::move в Set методе класса
От: MTD https://github.com/mtrempoltsev
Дата: 09.02.18 17:21
Оценка:
Здравствуйте, rg45, Вы писали:

R>Использование альтернативного имени для функции, принимающей rvalue ссылку я считаю неоправданным в данном случае, так как от этого пострадает обобщенность кода.


И это хорошо, не надо пытаться использовать корову как ежа, и если с ООП еще более менее разобрались, то с шаблонами все еще продолжают набивать шишки.

R>Если у вас уже имеется набор шаблонных функций, вызывающих метод Set, используя forwarding references, то после переименования Set в Take весь этот набор вам придется продублировать.


И правильно, так как семантика у передачи владения и просто передачи ссылки или копии разная.
Re[8]: Применение std::move в Set методе класса
От: AlexGin Беларусь  
Дата: 09.02.18 18:14
Оценка:
Здравствуйте, rumit7, Вы писали:

AG>ИМХО передавать объект по значению, а не по ссылке (и не по указателю): не очень правильно, с точки зрения

AG>нерационального использования стековой памяти.

R>если брать во внимание copy elision, то можно с этим поспорить..


R>"Want Speed? Pass by Value"

R>https://stackoverflow.com/a/24543391/8567492
R>https://stackoverflow.com/a/11373695/8567492

Представим, что мы абстрагируемся от семантики перемещения (по крайней мере, в части передачи параметра в метод).
Предположим также, что внутри метода нет std::move(...).

Тогда такой вот момент:
с точки зрения как памяти, так и производительности, передача параметра по значению (в C++11 и новее) — даст выигрыш по сравнению с передачей по константной l-value ссылке, или нет?

P.S. Насчет r-value ссылки: в этом случае выигрыш, по сравнению с константной l-value ссылкой, бесспорно будет.
Re[3]: Применение std::move в Set методе класса
От: AlexGin Беларусь  
Дата: 09.02.18 18:21
Оценка:
Здравствуйте, uzhas, Вы писали:

U>а ещё я использую слово provide для геттеров, которые делают что-то умное, а не просто делают return уже готового объекта. например, ищут\вставляют в кеш или лезут в файл\сеть

+100500
Я в таких случаях использую слово "Retrieve"

U>если надо пошариться в мапе, то я всё же использую find в имени метода

...вполне логично...
Re[7]: Применение std::move в Set методе класса
От: rg45 СССР  
Дата: 09.02.18 20:00
Оценка:
Здравствуйте, MTD, Вы писали:

MTD>Нет ничего сомнительного в том, чтобы писать понятные и надежные программы.


Какая нафиг понятность, когда разработчик постоянно должен напрягать мозги, что ему лучше подходит Set или Take, в то время как реализация способна бы разрулить все автоматически наилучшим образом. Что Set("Hello"), что Set(str) — для разработчика это одна и та же операция, не должен он в этом месте напрягаться.

А надежность в чем? Что помешает разработчику игнорировать Take, а исполльзовать только Set? Вот это прекрасно все компилируется:

void Set(const std::string&);

std::string str;

Set("Hello");
Set(std::move(str));


Причем внутри Set всегда будет создаваться копия, когда нужно и когда не нужно. Я даже уже догадываюсь что ты ответишь: "разрабочик сам себе злобный Буратино, раз не использует Take". Ну так точно так же он сам себе злобный Буратино, если использует объект после move.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[8]: Применение std::move в Set методе класса
От: MTD https://github.com/mtrempoltsev
Дата: 09.02.18 20:10
Оценка:
Здравствуйте, rg45, Вы писали:

R>Какая нафиг понятность, когда разработчик постоянно должен напрягать мозги, что ему лучше подходит Set или Take


А что тут напрягать? Надо передать владение — take, не надо — set, зато по коду сразу видна логика.

R>Что Set("Hello"), что Set(str) — для разработчика это одна и та же операция, не должен он в этом месте напрягаться.


Не должен, но мы же про С++ говорим — здесь везде надо напрягаться.

R>Что помешает разработчику игнорировать Take, а исполльзовать только Set?


Ничто не помешает, в С++ вообще на каждом шагу возможность выстрелить в ногу, но это не значит, что надо понижать самодокументируемость кода.

R>Причем внутри Set всегда будет создаваться копия, когда нужно и когда не нужно.


Смотря как set написать, если передавать по значению, то в некоторых случаях никаких копий создано не будет.

R>Я даже уже догадываюсь что ты ответишь: "разрабочик сам себе злобный Буратино, раз не использует Take". Ну так точно так же он сам себе злобный Буратино, если использует объект после move.


Два раза да
Re[5]: Применение std::move в Set методе класса
От: rg45 СССР  
Дата: 09.02.18 20:12
Оценка:
Здравствуйте, MTD, Вы писали:

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


R>>Использование альтернативного имени для функции, принимающей rvalue ссылку я считаю неоправданным в данном случае, так как от этого пострадает обобщенность кода.


MTD>И это хорошо, не надо пытаться использовать корову как ежа, и если с ООП еще более менее разобрались, то с шаблонами все еще продолжают набивать шишки.


Еж, подброшенный в воздух, не становится коровой, а становится всего лишь ежом с другим storage duration. Но ни разу не повод смотреть на ежа как на корову.

R>>Если у вас уже имеется набор шаблонных функций, вызывающих метод Set, используя forwarding references, то после переименования Set в Take весь этот набор вам придется продублировать.


MTD>И правильно, так как семантика у передачи владения и просто передачи ссылки или копии разная.


Нет никакого владения у временных объектов — они временные! A move — это всего лишь явный способ разрешить обрабатывать обычный объект, как временный, и разобрать его на запчасти. Чувствуешь разницу между "передать владение" и "разобрать на запчасти"?
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[9]: Применение std::move в Set методе класса
От: rg45 СССР  
Дата: 09.02.18 20:23
Оценка: +1
Здравствуйте, MTD, Вы писали:

MTD>А что тут напрягать?


Как минимум я должен задуматься, что лучше вызвать take("Hello") или set("Hello") и чем они отличаются.

MTD>Надо передать владение — take, не надо — set, зато по коду сразу видна логика.


Нет здесь никакого владения. И передачи владения тоже нет. Есть явный способ разрешить рассматривать обычный объект как временный.

R>>Что Set("Hello"), что Set(str) — для разработчика это одна и та же операция, не должен он в этом месте напрягаться.


MTD>Не должен, но мы же про С++ говорим — здесь везде надо напрягаться.


Так чего тогда беспокоиться — нужно просто запомнить, что использовать объект после move нельзя, а не добавлять себе и пользователям дурную работу.

MTD>Ничто не помешает, в С++ вообще на каждом шагу возможность выстрелить в ногу, но это не значит, что надо понижать самодокументируемость кода.


От добавления ненужных операций самодокументируемость не улучшается.

MTD>Смотря как set написать, если передавать по значению, то в некоторых случаях никаких копий создано не будет.


Так а зачем нам тогда take вообще? Давайте просто скажем, что нафиг нам та move семантика у нас и так все замечательно.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[6]: Применение std::move в Set методе класса
От: MTD https://github.com/mtrempoltsev
Дата: 09.02.18 20:23
Оценка:
Здравствуйте, rg45, Вы писали:

R>Нет никакого владения у временных объектов — они временные!


Щито? Временный объект от "не временного" не отличается вообще никак. Порядок конструирования и разрушения одинаков.

R>A move — это всего лишь явный способ разрешить обрабатывать обычный объект, как временный, и разобрать его на запчасти.


move — это просто каст к определенному виду ссылки, чтобы компилятор мог понять какой метод вызвать.

R>Чувствуешь разницу между "передать владение" и "разобрать на запчасти"?


Пошла лирика — это к гуманитариям, мне не понятно.
Re[10]: Применение std::move в Set методе класса
От: MTD https://github.com/mtrempoltsev
Дата: 09.02.18 20:29
Оценка:
Здравствуйте, rg45, Вы писали:

R>Как минимум я должен задуматься, что лучше вызвать take("Hello") или set("Hello") и чем они отличаются.


Назвался груздем — полезай в кузов. На С++ надо постоянно думать, иначе лучше сразу Яву брать или еще что — выйдет и надежней и проще и код быстрее.

MTD>>Надо передать владение — take, не надо — set, зато по коду сразу видна логика.


R>Нет здесь никакого владения. И передачи владения тоже нет. Есть явный способ разрешить рассматривать обычный объект как временный.


Как нет, если есть? Оно конечно все руками реализуется, но тем не менее.

MTD>>Не должен, но мы же про С++ говорим — здесь везде надо напрягаться.


R>Так чего тогда беспокоиться — нужно просто запомнить, что использовать объект после move нельзя, а не добавлять себе и пользователям дурную работу.


Нет, это облегчать читателям твоего кода жизнь.

MTD>>Ничто не помешает, в С++ вообще на каждом шагу возможность выстрелить в ногу, но это не значит, что надо понижать самодокументируемость кода.


R>От добавления ненужных операций самодокументируемость не улучшается.


Они не ненужные.

MTD>>Смотря как set написать, если передавать по значению, то в некоторых случаях никаких копий создано не будет.


R>Так а зачем нам тогда take вообще?


Чтобы явно продемонстрировать намерение передать владение.

R>Давайте просто скажем, что нафиг нам та move семантика у нас и так все замечательно.


Нет, я с твоей позицией не согласен, тебе может и нафиг, а мне нет.
Re[7]: Применение std::move в Set методе класса
От: rg45 СССР  
Дата: 09.02.18 20:36
Оценка:
Здравствуйте, MTD, Вы писали:

R>>Нет никакого владения у временных объектов — они временные!


MTD>Щито? Временный объект от "не временного" не отличается вообще никак.


Отличается — у временного объекта нет имени, у него нельзя получить адрес, у него другой storage duration.

MTD>Порядок конструирования и разрушения одинаков.


Разумеется. А каким боком порядок конструирования к владению?

MTD>move — это просто каст к определенному виду ссылки, чтобы компилятор мог понять какой метод вызвать.


Совершенно верно. И этот каст явно делает разработчик, тем самым позволяя обращаться с обычным объектом как с временным. А разве что-то другое сказал?

R>>Чувствуешь разницу между "передать владение" и "разобрать на запчасти"?

MTD>Пошла лирика — это к гуманитариям, мне не понятно.

Попробую выразиться иначе — move семантика не является передачей владения. Так понятнее?
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[11]: Применение std::move в Set методе класса
От: rg45 СССР  
Дата: 09.02.18 20:40
Оценка:
Здравствуйте, MTD, Вы писали:

R>>Как минимум я должен задуматься, что лучше вызвать take("Hello") или set("Hello") и чем они отличаются.


MTD>Назвался груздем — полезай в кузов. На С++ надо постоянно думать, иначе лучше сразу Яву брать или еще что — выйдет и надежней и проще и код быстрее.


То, что нужно постоянно думать вовсе не означет, что нужно создавать дурные заботы себе и другим. Зачем вовлекать человека с его человеческим фактором в процесс, который на 100% разруливается автоматически.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 09.02.2018 20:43 rg45 . Предыдущая версия .
Re[12]: Применение std::move в Set методе класса
От: MTD https://github.com/mtrempoltsev
Дата: 09.02.18 20:42
Оценка:
Здравствуйте, rg45, Вы писали:

R>То, что нужно постоянно думать вовсе не означет, что нужно создавать дурные заботы себе и другим.


Совершенно верно, поэтому надо давать осмысленные имена и избегать одинаковых имен для методов с разной семантикой.
Re[8]: Применение std::move в Set методе класса
От: MTD https://github.com/mtrempoltsev
Дата: 09.02.18 20:48
Оценка:
Здравствуйте, rg45, Вы писали:

MTD>>Порядок конструирования и разрушения одинаков.


R>Разумеется. А каким боком порядок конструирования к владению?


Гугли RAII — в конструкторе захватили, в деструкторе освободили.

R>Попробую выразиться иначе — move семантика не является передачей владения. Так понятнее?


Реализовать ты можешь любое поведение, но перемещение (move семантика), с точки зрения здравого смысла — ничто другое, как передача владения.
Re[13]: Применение std::move в Set методе класса
От: rg45 СССР  
Дата: 09.02.18 20:49
Оценка:
Здравствуйте, MTD, Вы писали:

MTD>Совершенно верно, поэтому надо давать осмысленные имена и избегать одинаковых имен для методов с разной семантикой.


Совершенно верно, поэтому надо давать осмысленные имена и избегать разных имен для методов с одинаковой семантикой.
--
Не можешь достичь желаемого — пожелай достигнутого.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.