Здравствуйте, rg45, Вы писали:
R>Я бы выбрал std::vector<int>&&. А с этим возникают какие-то трудности?
Возвращение ссылки на член класса. Я не уверен, что так не будет неопределённого поведения...
Здравствуйте, B0FEE664, Вы писали:
BFE>Возвращение ссылки на член класса. Я не уверен, что так не будет неопределённого поведения...
Ну если эта ссылка будет использована после прекращения времени жизни объекта, то конечно будет. Но это уже не имеет прямого отношения ни к move семантике, ни к rvalue ссылкам ведь ровно такая же проблема существует и со старыми добрыми lvalue ссылками. Я убежден, что это проблема вызымающего кода, а не разрабатываемого класса. Невозможно встроить в класс все возможные и невозможные защиты.
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, Constructor, Вы писали:
BFE>>Какой тип следует возвращать методом 'get() &&;' ?
C>Возвращать, конечно, стоит только по значению (как и всегда в подобных случаях).
Впервые слышу о таком правиле. Почему, например, std::optional::value не следует этому правилу?
ИМХО, ты упускаешь из виду, что если вызвающий код вызвал у rvalue объекта медод GetVector, то никаким другим способом он этот объект использовать уже не cможет. А если сможет, то либо это не rvalue объект, либо он использует несколько раз move для одного и того же объекта. Так или иначе, ошибиться случайно невозможно и никаких ошибок не возникнет в корректно написанном вызывающем коде.
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, rg45, Вы писали:
R>Здравствуйте, Constructor, Вы писали:
BFE>>>Какой тип следует возвращать методом 'get() &&;' ?
C>>Возвращать, конечно, стоит только по значению (как и всегда в подобных случаях).
R>Впервые слышу о таком правиле. Почему, например, std::optional::value не следует этому правилу?
Стандартная библиотека вряд ли может служить пособием по хорошему стилю написания C++-кода.
R>Так или иначе, ошибиться случайно невозможно и никаких ошибок не возникнет в корректно написанном вызывающем коде.
Здравствуйте, Constructor, Вы писали:
C>Возвращать, конечно, стоит только по значению (как и всегда в подобных случаях).
R>>Впервые слышу о таком правиле. Почему, например, std::optional::value не следует этому правилу?
C>Стандартная библиотека вряд ли может служить пособием по хорошему стилю написания C++-кода.
Спорное утверждение. Стандартная библиотека описана в стандарте языка и является его неотъемлемой частью. А вот ссыылок на источники правила "всегда возвращать по значению" ты так и не предоставил.
R>>Так или иначе, ошибиться случайно невозможно и никаких ошибок не возникнет в корректно написанном вызывающем коде.
C>int main() C>{ C> auto&& bar = Foo{}.get_bar(); C> std::cout << "---------------------" << std::endl; C> bar.print_x(); C>} C>[/ccode] C>Следующий код корректно написан?
Нет конечно, этот код порождает битую ссылку, а потом ее использует. Это примерно то же самое, что и это:
auto bar = std::srtring("Hello!").c_str();
std::cout << bar << std::endl;
Только косяк здесь в клиентском коде, а вовсе не в библиотеке.
C>Если поменять Bar&& get_bar() && на Bar get_bar() &&, то таких проблем не возникнет.
И если поменять auto&& bar = ... на auto bar = ..., то тоже таких проблем не возникнет.
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, rg45, Вы писали:
C>>Стандартная библиотека вряд ли может служить пособием по хорошему стилю написания C++-кода.
R>Спорное утверждение. Стандартная библиотека описана в стандарте языка и является его неотъемлемой частью.
Стандартная библиотека является частью стандарта языка, безусловно. Каким образом это противоречит тому, что она "вряд ли может служить пособием по хорошему стилю написания C++-кода"?
R>А вот ссыылок на источники правила "всегда возвращать по значению" ты так и не предоставил.
О каком правиле идет речь? Я выразил свое мнение.
Но мне всегда казалось, что это достаточно общее место: возврат r-value ссылки (в особенности при передаче владения объектом, на который указывает ссылка) — это небезопасно и не рекомендуется (т.е. допустимо только в каких-то весьма и весьма частных случаях). Например, см. вопрос на StackOverflow. В данном случае ситуация дополнительно усугубляется тем, что мы точно знаем (благодаря ref-qualifier), что объект, который возвращается по ссылке, является частью другого объекта, который будет уничтожен в конце выражения.
Здравствуйте, Constructor, Вы писали:
C>Стандартная библиотека является частью стандарта языка, безусловно. Каким образом это противоречит тому, что она "вряд ли может служить пособием по хорошему стилю написания C++-кода"?
Нравится тебе этот стиль или нет, но это наиболее широко используемая библиотека, с которой знаком любой разработчик С++. И, следуя этому стилю, ты, по крайней мере, не будешь нарушать принцип наименьшего удивления.
C>О каком правиле идет речь? Я выразил свое мнение.
Меня удивила категоричность, с которой ты высказал свое мнение. Прозвучало так, как будто это уже какая-то общепринятая практика.
C>Но мне всегда казалось, что это достаточно общее место: возврат r-value ссылки (в особенности при передаче владения объектом, на который указывает ссылка) — это небезопасно и не рекомендуется (т.е. допустимо только в каких-то весьма и весьма частных случаях). Например, см. вопрос на StackOverflow. В данном случае ситуация дополнительно усугубляется тем, что мы точно знаем (благодаря ref-qualifier), что объект, который возвращается по ссылке, является частью другого объекта, который будет уничтожен в конце выражения.
Ну, до сих пор прозвучало единственное обоснование, почему нужно возвращать значение, а не ссылку — это то, что пользователь класса может написать так:
auto&& bar = Foo{}.get_bar();
Ну так пользователь может еще и не такое написать. Например, он може написать вот так:
И вот здесь он уж точно удивится, нафига мы делаем столько никому ненужных копий тяжелых объектов.
Когда пользователь пишет конструкцию наподобие Foo{}.get_bar() он, вообще-то, должен понимать, ЧТО он вызывает, что получает и каково время жизни возникающих объектов. А если он этого не понимает, то как соломку ни стели, он все равно найдет способ выстрелить себе в ногу.
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, rg45, Вы писали:
C>>Стандартная библиотека является частью стандарта языка, безусловно. Каким образом это противоречит тому, что она "вряд ли может служить пособием по хорошему стилю написания C++-кода"?
R>Нравится тебе этот стиль или нет, но это наиболее широко используемая библиотека, с которой знаком любой разработчик С++. И, следуя этому стилю, ты, по крайней мере, не будешь нарушать принцип наименьшего удивления.
Какой "этот стиль"? Я говорил о "хорошем стиле" — best practices, которые существуют на данный момент в языке. И библиотека им зачастую не соответствует (иногда это происходит просто из-за того, что она не поспевает за изменениями в языке; иногда ради сохранения обратной совместимости; но бывают и ошибки, и просчеты, и недосмотры-недоделки, и чудачества).
C>>О каком правиле идет речь? Я выразил свое мнение.
R>Меня удивила категоричность, с которой ты высказал свое мнение. Прозвучало так, как будто это уже какая-то общепринятая практика.
Прошу прощения за (возможно неуместную) категоричность, но у меня просто глаза на лоб полезли, когда я увидел код, возвращающий r-value ссылку.
C>>Но мне всегда казалось, что это достаточно общее место: возврат r-value ссылки (в особенности при передаче владения объектом, на который указывает ссылка) — это небезопасно и не рекомендуется (т.е. допустимо только в каких-то весьма и весьма частных случаях). Например, см. вопрос на StackOverflow. В данном случае ситуация дополнительно усугубляется тем, что мы точно знаем (благодаря ref-qualifier), что объект, который возвращается по ссылке, является частью другого объекта, который будет уничтожен в конце выражения.
R>Ну, до сих пор прозвучало единственное обоснование, почему нужно возвращать значение, а не ссылку — это то, что пользователь класса может написать так:
R>
R>И вот здесь он уж точно удивится, нафига мы делаем столько никому ненужных копий тяжелых объектов.
О каких копиях идет речь? В данном случае будет вызываться цепочка конструкторов перемещения, относительно быстрых/эффективных по сравнению с конструкторами копирования.
Но такой код сам по себе вряд ли можно назвать "хорошим" (особенно если фигурирующие в нем объекты "тяжелые").
R>Когда пользователь пишет конструкцию наподобие Foo{}.get_bar() он, вообще-то, должен понимать, ЧТО он вызывает, что получает и каково время жизни возникающих объектов. А если он этого не понимает, то как соломку ни стели, он все равно найдет способ выстрелить себе в ногу.
В данном случае возможность написания сомнительного по стилю кода идет в комплекте с неиллюзорной опасностью внезапных отстрелов конечностей. Лично я склоняюсь к варианту написания потенциально более медленного кода без сопутствующей опции отстрела.
Здравствуйте, Constructor, Вы писали:
C>Вот еще одно обоснование, если прежнее не слишком нравится:
Да, этот пример выглядит убедительнее.
R>>И вот здесь он уж точно удивится, нафига мы делаем столько никому ненужных копий тяжелых объектов.
C>О каких копиях идет речь? В данном случае будет вызываться цепочка конструкторов перемещения, относительно быстрых/эффективных по сравнению с конструкторами копирования.
Я начинаю склоняться в твою сторону. Беру таймаут "на подумать".
--
Не можешь достичь желаемого — пожелай достигнутого.
Здравствуйте, Constructor, Вы писали:
C>Прошу прощения за (возможно неуместную) категоричность, но у меня просто глаза на лоб полезли, когда я увидел код, возвращающий r-value ссылку.
твоё "глаза полезли" опять говорит о категоричности
сигнатуру "foo() &&" в первую очередь придумали для лучшего перформанса. как сайд-эффект получили ещё одну возможность отстрелить ногу
возвращать vector&& считаю допустимой практикой (и да, это реальная практика). люди пользуются успешно, несмотря на возможные проблемы при использовании
точно так же люди используют голые указатели. страшно и крешдампы возможны, зато быстро
с точки зрения теории и стандарта опять же никаких нарушений нет. можно возвращать и по значению и по &&
теперь по поводу std::move тебе вопрос: ты готов сделать return std::move или сделаешь копию члена класса при возвращении по значению? можно развернуто ответить на этот вопрос
спасибо
B0FEE664:
BFE>Какой тип следует возвращать методом 'get() &&;' ?
Полагаю, если было бы понятно, зачем такой get вообще нужен, подобных вопросов бы не возникало. Ну, а от нечего делать можно ещё подумать, что б этакое вернуть из
А то те скромные четыре метода get выглядят как-то несолидно, прям халтура какая-то. Вот если там с десяток вариаций get будет, то уже точно никто не посмеет усомниться в предусмотрительности автора. Кстати, там noexcept очень неплохо бы смотрелся.
Здравствуйте, N. I., Вы писали:
NI>Полагаю, если было бы понятно, зачем такой get вообще нужен, подобных вопросов бы не возникало.
Друзь, давай ответ в студию
Здравствуйте, uzhas, Вы писали:
C>>Прошу прощения за (возможно неуместную) категоричность, но у меня просто глаза на лоб полезли, когда я увидел код, возвращающий r-value ссылку.
U>твоё "глаза полезли" опять говорит о категоричности
Грешен, каюсь.
U>с точки зрения теории и стандарта опять же никаких нарушений нет. можно возвращать и по значению и по &&
В этом не было никаких сомнений.
U>теперь по поводу std::move тебе вопрос: ты готов сделать return std::move или сделаешь копию члена класса при возвращении по значению? можно развернуто ответить на этот вопрос
К сожалению, по-видимому, никакой легальный elision в данном случае не сработает, поэтому необходимости в простом копировании нет. Это один из тех редких случаев, когда нужен именно return std::move(smth);. Или тут какой-то подвох есть?
Здравствуйте, Constructor, Вы писали:
U>>с точки зрения теории и стандарта опять же никаких нарушений нет. можно возвращать и по значению и по && C>В этом не было никаких сомнений.
У ТС были сомнения: http://rsdn.org/forum/cpp/7035221.1
C>К сожалению, по-видимому, никакой легальный elision в данном случае не сработает, поэтому необходимости в простом копировании нет. Это один из тех редких случаев, когда нужен именно return std::move(smth);. Или тут какой-то подвох есть?
я думал в таком направлении: не может ли так случиться, что метод дернут дважды и во втором случае результат уже будет пустой (ну или valid, but unspecified state, для буквоедов) ?
Если поставленная задача заключается в том, чтобы найти какое-нибудь применение для ref-qualifiers, то можно сделать типом возврата void и подождать, пока кто-нибудь не захочет использовать get с rvalue и не заценит юмор (есть вероятность того, что такое вообще никогда не случится).
Если использование ref-qualifiers диктуется реальными нуждами, то должны быть и вполне конкретные примеры вызова таких версий get, где уже будет более-менее видно, что оттуда выгодно возвращать.
Если нет никаких поводов связываться с ref-qualifiers, то и не надо там их использовать вовсе. Вот, как-то так.
Здравствуйте, uzhas, Вы писали:
C>>К сожалению, по-видимому, никакой легальный elision в данном случае не сработает, поэтому необходимости в простом копировании нет. Это один из тех редких случаев, когда нужен именно return std::move(smth);. Или тут какой-то подвох есть?
U>я думал в таком направлении: не может ли так случиться, что метод дернут дважды и во втором случае результат уже будет пустой (ну или valid, but unspecified state, для буквоедов) ?
Навскидку такое возможно только при прямом вредительстве, да и опасности особой тут не будет, т.к. состояние все-таки должно быть valid, хоть и unspecified.