Здравствуйте, 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 '=').
ИМХО передавать объект по значению, а не по ссылке (и не по указателю): не очень правильно, с точки зрения
нерационального использования стековой памяти.
Здравствуйте, AlexGin, Вы писали:
AG>Здравствуйте, rumit7, Вы писали:
R>>... но почему-бы не рассмотреть еще пару вариантов, каждый по отдельности вместо предлагаемых Вами выше:
R>>
AG>ИМХО передавать объект по значению, а не по ссылке (и не по указателю): не очень правильно, с точки зрения AG>нерационального использования стековой памяти.
если брать во внимание copy elision, то можно с этим поспорить..
Здравствуйте, 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 в имени метода
Здравствуйте, AlexGin, Вы писали:
AG>ИМХО передавать объект по значению, а не по ссылке (и не по указателю): не очень правильно, с точки зрения AG>нерационального использования стековой памяти.
Это очень правильно для небольших структур (до 4 машинных слов) имеющих тривиальный конструктор и деструктор — тогда он просто будет передан через регистры без использования стека.
Здравствуйте, rg45, Вы писали:
R>Если разобраться, для чего может понадобиться Take? Только для того, чтоб защититься от использования объекта, после того, как мы разрешили его раскурочить, применив к нему move? Ну это достаточно сомнительное желание, ИМХО, не следует адаптировать дизайн под некорректное использование.
Нет ничего сомнительного в том, чтобы писать понятные и надежные программы.
Здравствуйте, rg45, Вы писали:
R>Использование альтернативного имени для функции, принимающей rvalue ссылку я считаю неоправданным в данном случае, так как от этого пострадает обобщенность кода.
И это хорошо, не надо пытаться использовать корову как ежа, и если с ООП еще более менее разобрались, то с шаблонами все еще продолжают набивать шишки.
R>Если у вас уже имеется набор шаблонных функций, вызывающих метод Set, используя forwarding references, то после переименования Set в Take весь этот набор вам придется продублировать.
И правильно, так как семантика у передачи владения и просто передачи ссылки или копии разная.
Представим, что мы абстрагируемся от семантики перемещения (по крайней мере, в части передачи параметра в метод).
Предположим также, что внутри метода нет std::move(...).
Тогда такой вот момент:
с точки зрения как памяти, так и производительности, передача параметра по значению (в C++11 и новее) — даст выигрыш по сравнению с передачей по константной l-value ссылке, или нет?
P.S. Насчет r-value ссылки: в этом случае выигрыш, по сравнению с константной l-value ссылкой, бесспорно будет.
Здравствуйте, uzhas, Вы писали:
U>а ещё я использую слово provide для геттеров, которые делают что-то умное, а не просто делают return уже готового объекта. например, ищут\вставляют в кеш или лезут в файл\сеть
+100500
Я в таких случаях использую слово "Retrieve"
U>если надо пошариться в мапе, то я всё же использую find в имени метода
...вполне логично...
Здравствуйте, MTD, Вы писали:
MTD>Нет ничего сомнительного в том, чтобы писать понятные и надежные программы.
Какая нафиг понятность, когда разработчик постоянно должен напрягать мозги, что ему лучше подходит Set или Take, в то время как реализация способна бы разрулить все автоматически наилучшим образом. Что Set("Hello"), что Set(str) — для разработчика это одна и та же операция, не должен он в этом месте напрягаться.
А надежность в чем? Что помешает разработчику игнорировать Take, а исполльзовать только Set? Вот это прекрасно все компилируется:
Причем внутри Set всегда будет создаваться копия, когда нужно и когда не нужно. Я даже уже догадываюсь что ты ответишь: "разрабочик сам себе злобный Буратино, раз не использует Take". Ну так точно так же он сам себе злобный Буратино, если использует объект после move.
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, rg45, Вы писали:
R>Какая нафиг понятность, когда разработчик постоянно должен напрягать мозги, что ему лучше подходит Set или Take
А что тут напрягать? Надо передать владение — take, не надо — set, зато по коду сразу видна логика.
R>Что Set("Hello"), что Set(str) — для разработчика это одна и та же операция, не должен он в этом месте напрягаться.
Не должен, но мы же про С++ говорим — здесь везде надо напрягаться.
R>Что помешает разработчику игнорировать Take, а исполльзовать только Set?
Ничто не помешает, в С++ вообще на каждом шагу возможность выстрелить в ногу, но это не значит, что надо понижать самодокументируемость кода.
R>Причем внутри Set всегда будет создаваться копия, когда нужно и когда не нужно.
Смотря как set написать, если передавать по значению, то в некоторых случаях никаких копий создано не будет.
R>Я даже уже догадываюсь что ты ответишь: "разрабочик сам себе злобный Буратино, раз не использует Take". Ну так точно так же он сам себе злобный Буратино, если использует объект после move.
Здравствуйте, MTD, Вы писали:
MTD>Здравствуйте, rg45, Вы писали:
R>>Использование альтернативного имени для функции, принимающей rvalue ссылку я считаю неоправданным в данном случае, так как от этого пострадает обобщенность кода.
MTD>И это хорошо, не надо пытаться использовать корову как ежа, и если с ООП еще более менее разобрались, то с шаблонами все еще продолжают набивать шишки.
Еж, подброшенный в воздух, не становится коровой, а становится всего лишь ежом с другим storage duration. Но ни разу не повод смотреть на ежа как на корову.
R>>Если у вас уже имеется набор шаблонных функций, вызывающих метод Set, используя forwarding references, то после переименования Set в Take весь этот набор вам придется продублировать.
MTD>И правильно, так как семантика у передачи владения и просто передачи ссылки или копии разная.
Нет никакого владения у временных объектов — они временные! A move — это всего лишь явный способ разрешить обрабатывать обычный объект, как временный, и разобрать его на запчасти. Чувствуешь разницу между "передать владение" и "разобрать на запчасти"?
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, MTD, Вы писали:
MTD>А что тут напрягать?
Как минимум я должен задуматься, что лучше вызвать take("Hello") или set("Hello") и чем они отличаются.
MTD>Надо передать владение — take, не надо — set, зато по коду сразу видна логика.
Нет здесь никакого владения. И передачи владения тоже нет. Есть явный способ разрешить рассматривать обычный объект как временный.
R>>Что Set("Hello"), что Set(str) — для разработчика это одна и та же операция, не должен он в этом месте напрягаться.
MTD>Не должен, но мы же про С++ говорим — здесь везде надо напрягаться.
Так чего тогда беспокоиться — нужно просто запомнить, что использовать объект после move нельзя, а не добавлять себе и пользователям дурную работу.
MTD>Ничто не помешает, в С++ вообще на каждом шагу возможность выстрелить в ногу, но это не значит, что надо понижать самодокументируемость кода.
От добавления ненужных операций самодокументируемость не улучшается.
MTD>Смотря как set написать, если передавать по значению, то в некоторых случаях никаких копий создано не будет.
Так а зачем нам тогда take вообще? Давайте просто скажем, что нафиг нам та move семантика у нас и так все замечательно.
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, rg45, Вы писали:
R>Нет никакого владения у временных объектов — они временные!
Щито? Временный объект от "не временного" не отличается вообще никак. Порядок конструирования и разрушения одинаков.
R>A move — это всего лишь явный способ разрешить обрабатывать обычный объект, как временный, и разобрать его на запчасти.
move — это просто каст к определенному виду ссылки, чтобы компилятор мог понять какой метод вызвать.
R>Чувствуешь разницу между "передать владение" и "разобрать на запчасти"?
Пошла лирика — это к гуманитариям, мне не понятно.
Здравствуйте, rg45, Вы писали:
R>Как минимум я должен задуматься, что лучше вызвать take("Hello") или set("Hello") и чем они отличаются.
Назвался груздем — полезай в кузов. На С++ надо постоянно думать, иначе лучше сразу Яву брать или еще что — выйдет и надежней и проще и код быстрее.
MTD>>Надо передать владение — take, не надо — set, зато по коду сразу видна логика.
R>Нет здесь никакого владения. И передачи владения тоже нет. Есть явный способ разрешить рассматривать обычный объект как временный.
Как нет, если есть? Оно конечно все руками реализуется, но тем не менее.
MTD>>Не должен, но мы же про С++ говорим — здесь везде надо напрягаться.
R>Так чего тогда беспокоиться — нужно просто запомнить, что использовать объект после move нельзя, а не добавлять себе и пользователям дурную работу.
Нет, это облегчать читателям твоего кода жизнь.
MTD>>Ничто не помешает, в С++ вообще на каждом шагу возможность выстрелить в ногу, но это не значит, что надо понижать самодокументируемость кода.
R>От добавления ненужных операций самодокументируемость не улучшается.
Они не ненужные.
MTD>>Смотря как set написать, если передавать по значению, то в некоторых случаях никаких копий создано не будет.
R>Так а зачем нам тогда take вообще?
Чтобы явно продемонстрировать намерение передать владение.
R>Давайте просто скажем, что нафиг нам та move семантика у нас и так все замечательно.
Нет, я с твоей позицией не согласен, тебе может и нафиг, а мне нет.
Здравствуйте, MTD, Вы писали:
R>>Нет никакого владения у временных объектов — они временные!
MTD>Щито? Временный объект от "не временного" не отличается вообще никак.
Отличается — у временного объекта нет имени, у него нельзя получить адрес, у него другой storage duration.
MTD>Порядок конструирования и разрушения одинаков.
Разумеется. А каким боком порядок конструирования к владению?
MTD>move — это просто каст к определенному виду ссылки, чтобы компилятор мог понять какой метод вызвать.
Совершенно верно. И этот каст явно делает разработчик, тем самым позволяя обращаться с обычным объектом как с временным. А разве что-то другое сказал?
R>>Чувствуешь разницу между "передать владение" и "разобрать на запчасти"? MTD>Пошла лирика — это к гуманитариям, мне не понятно.
Попробую выразиться иначе — move семантика не является передачей владения. Так понятнее?
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, MTD, Вы писали:
R>>Как минимум я должен задуматься, что лучше вызвать take("Hello") или set("Hello") и чем они отличаются.
MTD>Назвался груздем — полезай в кузов. На С++ надо постоянно думать, иначе лучше сразу Яву брать или еще что — выйдет и надежней и проще и код быстрее.
То, что нужно постоянно думать вовсе не означет, что нужно создавать дурные заботы себе и другим. Зачем вовлекать человека с его человеческим фактором в процесс, который на 100% разруливается автоматически.
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, rg45, Вы писали:
MTD>>Порядок конструирования и разрушения одинаков.
R>Разумеется. А каким боком порядок конструирования к владению?
Гугли RAII — в конструкторе захватили, в деструкторе освободили.
R>Попробую выразиться иначе — move семантика не является передачей владения. Так понятнее?
Реализовать ты можешь любое поведение, но перемещение (move семантика), с точки зрения здравого смысла — ничто другое, как передача владения.