σ>>>>Т.е. внутри buildMapresult обозначает объект вне лайфтайма? Значит на нём нельзя вызывать методы.
TB>>>Не понял проблемы. Да, адрес у объектов один и тот же
σ>>У объектов? При NRVO это один объект.
TB>>>но в одном контексте считается, что по этому адресу объект менять нельзя, а в другом — что можно.
σ>>Что значит «считается»?
S>Не очень понятна суть вопросов.
По невтемному примеру я понял.
S> В С++ даже у константных объектов есть период времени, когда они константами не считаются
Здравствуйте, σ, Вы писали:
TB>>>>но в одном контексте считается, что по этому адресу объект менять нельзя, а в другом — что можно.
σ>>>Что значит «считается»?
S>>Не очень понятна суть вопросов.
σ>По невтемному примеру я понял.
А я не понял вопроса "Что значит «считается»?" относительно написанного тов.T4r4sB "но в одном контексте считается, что по этому адресу объект менять нельзя, а в другом — что можно."
Поэтому и обратился к вам за разъяснением.
S>> В С++ даже у константных объектов есть период времени, когда они константами не считаются
σ>Как это относится к коду в https://rsdn.org/forum/cpp/8581544.1
Это демонстрация сказанного тов.T4r4sB о том, что в одном контексте объект не константа, а в другом контексте уже константа. И все это относится к вашему вопросу "Что значит «считается»?"
Re[89]: Когда это наконец станет defined behavior?
S>>> В С++ даже у константных объектов есть период времени, когда они константами не считаются
σ>>Как это относится к коду в https://rsdn.org/forum/cpp/8581544.1
?
S>Это демонстрация сказанного тов.T4r4sB о том, что в одном контексте объект не константа, а в другом контексте уже константа.
Чел… Есть вполне чоткое определение что такое константный объект https://timsong-cpp.github.io/cppwp/n4868/basic.type.qualifier#def:object,const. И «контекстов» там как-то не замечено.
И во время конструирования в твоём примере объект тоже константный. Или, по-твоему, раз *this не const-qualified, это доказывает, что объект не константный?
Здравствуйте, σ, Вы писали:
S>>>> В С++ даже у константных объектов есть период времени, когда они константами не считаются
σ>>>Как это относится к коду в https://rsdn.org/forum/cpp/8581544.1
?
S>>Это демонстрация сказанного тов.T4r4sB о том, что в одном контексте объект не константа, а в другом контексте уже константа.
σ>Чел… Есть вполне чоткое определение что такое константный объект https://timsong-cpp.github.io/cppwp/n4868/basic.type.qualifier#def:object,const. И «контекстов» там как-то не замечено.
Есть у меня подозрение, что определение из стандарта в данном случае валидно для писателей компиляторов и статических анализаторов, а не для простого пользователя языка.
σ>И во время конструирования в твоём примере объект тоже константный. Или, по-твоему, раз *this не const-qualified, это доказывает, что объект не константный?
Если объект можно изменить, то он не константный, как-то так, да.
Re[88]: Когда это наконец станет defined behavior?
Здравствуйте, σ, Вы писали:
V>>Дудки! )) V>>Это одна область памяти, в которой по очереди живут два объекта.
σ>[class.copy.elision]/1: When certain criteria are met, an implementation is allowed to omit the copy/move construction of a class object, even if the constructor selected for the copy/move operation and/or the destructor for the object have side effects. In such cases, the implementation treats the source and target of the omitted copy/move operation as simply two different ways of referring to the same object.
И что, у тебя возникли проблемы с прочтением?
Описаны внутренние подробности реализации трюка.
σ>В общем, уровень (не)компетентности понятен.
Было бы понятно — не задавал бы глупых вопросов.
Согласно семантике речь идёт о двух разных объектах и эта семантика гарантируется.
Не согласен — обоснуй.
А что эту семантику можно реализовать через ссылку на одну и ту же область памяти в различных точках программы — так в этом и состоит суть RV-оптимизации. ))
Но эти ссылки никогда не валидны одновременно, во что тебя уже тыкали.
σ>— Да какой тут способ, дело не хитрое.
Угу, ты пытался рассуждать о неких проблемах.
Сформулировать проблему ты не смог, я попытался тебе помочь: http://www.rsdn.org/forum/cpp/8582417.1
(описан единственный сценарий, где две ссылки на объект живы одновременно)
Давай ты включишь уже моск и попытаешься, таки, сформулировать проблему.
Можно своими словами, бгг..
От одного сотрясения воздуха абревиатурами RVO/NRVO твои тараканы понятнее не становятся.
Re[90]: Когда это наконец станет defined behavior?
Здравствуйте, σ, Вы писали:
S>>Это демонстрация сказанного тов.T4r4sB о том, что в одном контексте объект не константа, а в другом контексте уже константа. σ>Чел… Есть вполне чоткое определение что такое константный объект https://timsong-cpp.github.io/cppwp/n4868/basic.type.qualifier#def:object,const. И «контекстов» там как-то не замечено.
А что ты хотел там увидеть?
Любой константный объект размером более машинного слова "унутре" всё-равно инициализируется за несколько операций, т.е. поля объекта при инициализации последовательно мутируются.
Разве это требуется дополнительно озвучивать?
σ>И во время конструирования в твоём примере объект тоже константный.
Каким образом? ))
Конструктор объекта не имеет понятия — создаёт ли он константный объект или мутабельный.
Re[82]: Когда это наконец станет defined behavior?
Здравствуйте, ·, Вы писали:
V>>В шарпе для такого сценария есть отдельно иммутабельный аналог map, и отдельно мутабельный builder для него. V>>В С++ не потребовалось создавать две сущности. ·>Именно, то же самое на шарпах делается с помощью интерфейса.
Интерфейсы и в плюсах доступны.
И прочие GOF-трюки, где иммутабельность может быть св-вом объекта, а может быть адаптером-view.
Просто это слишком частый сценарий, поэтому органично включён в язык, дабы достигать того же самого без лишних приседаний.
·>А две сущности в C++ тоже есть, просто неявно. Вместо явного интерфейса делается пара const- и просто-методов.
Так мы только выразительность языков и обсуждаем.
·>Константные объекты появляются не магически, а в определениях соответствующих полей и методов.
И в правилах языка, где константные методы можно вызывать у неконстантного объекта, а наоборот нет.
Например, св-во size() (count, amount и т.д.) определены как const, соответственно, описаны однажды для константного и неконстантного объекта.
И всё это продолжает работать в таких сценариях:
template<typename T>
void const logCollection(const T & collection) { ... }
// мутабельный объектauto cl = makeColllection();
auto size = cl.size(); // закешировали размер
logCollection(cl); // отдали куда-то по константной ссылкеfor(size_t i = 0; i < size; i++) // незачем запрашивать размер коллекции заново
V>>Этот сценарий может возникнуть не только вокруг иммутабельного map, где в шарпе постелили соломку, а вообще везде. ·>И там и там надо вводить два типа. Ведь T и const T это тоже разные типы.
Да.
Но описание типа программистом — одно.
V>>Собсно, только об этом и говорится в обсуждении (многократно по кругу) — что практически любой мутабельный тип можно использовать в т.ч. в иммутабельных сценариях. ·>"Практически" в том смысле если для типа правильно спроектирован const подтип. Ровно та же петрушка, что и с интерфейсом.
Разумеется.
Например, в шарпе интерфейс IEnumerator имеет read-only св-во Current.
Т.е., итераторы на интерфейсах сделаны не только потому что невозможно было накрутить логику как в плюсах через begin/end (в нынешнем шарпе уже можно сделать достаточно близко к плюсовомоу подходу, получив дешевизну), но еще потому что ДРУГОЙ интерфейс обеспечивает ДРУГУЮ семантику. В данном случае IEnumerator — это read-only семантика, т.е. употребима к мутабельным и немутабельным типам. В итоге для каждой коллекции приходится описывать еще и енумератор.
А вот если речь должна идти про сами типы-коллекции, то появляются пары Span/ReadOnlySpan, Memory/ReadOnlyMemory и т.д.
И это еще в шарпе по-лёгкoму, т.к. язык позволяет определять операторы преобразования, поэтому смогли определить неявное конструирование ReadOnly-версий из мутабельных.
В джаве пришлось бы делать двойную работу, окучивая каждую пару.
V>>Остальные сценарии, когда мутабельный объект подаётся по константной ссылке — это просто удобные гарантии, т.к. после вызова метода с таким аргументом ты можешь в коде рассуждать о том, что целевой объект в результате вызова некоей ф-ии с им-аргументом, не изменился. ·>Аналог final.
Не, final-метод в джаве обозначает другое.
Тут аналог readonly-метода в шарпе, но там оно допустимо только для методов структур.
Для GC-классов нет такой возможности.
Но в случае структур, да, шарп уже позволяет повторять семантику C++.
·>Суть моего тезиса в том, что семантика const в других ЯП выражается тоже, просто через другие механизмы языка.
Суть в том, что иммутабельность — такой же "трюк", облегчающий программистам жизнь, как и куча других.
Разумеется, иммутабельность можно обеспечить ср-вами любого языка, обладающего развитыми ср-вами инкапсуляции, и безо-всяких плюсовых const.
(а где эти ср-ва не развиты — там часто данные только иммутабельны, бгг, как в FP-языках)
Просто иммутабельность, всвязи с ростом многопоточности, ростом размеров оперативки (что привело к созданию больших объёмов данных в памяти) и постепенным улучшением оптимизирующих компиляторов, стала играть существенную роль в современном дизайне ПО.
И тут С++ задолго до, как грится, оказался к этому готов. ))
А вот почему более поздние джава и шарп оказались не готовы — вопрос вопросов, однако.
V>>>Дудки! )) V>>>Это одна область памяти, в которой по очереди живут два объекта.
σ>>[class.copy.elision]/1: When certain criteria are met, an implementation is allowed to omit the copy/move construction of a class object, even if the constructor selected for the copy/move operation and/or the destructor for the object have side effects. In such cases, the implementation treats the source and target of the omitted copy/move operation as simply two different ways of referring to the same object.
V>И что, у тебя возникли проблемы с прочтением?
Похоже, у тебя возникли, раз ты утверждаешь, что объекта якобы два.
V>Описаны внутренние подробности реализации трюка.
Что значит внутренние?
σ>>В общем, уровень (не)компетентности понятен.
V>Было бы понятно — не задавал бы глупых вопросов. V>Согласно семантике речь идёт о двух разных объектах и эта семантика гарантируется.
Гарантируется, что при NRVO объект один и тот же.
V>Не согласен — обоснуй.
У тебя возникли проблемы с прочтением?
V>А что эту семантику можно реализовать через ссылку на одну и ту же область памяти в различных точках программы — так в этом и состоит суть RV-оптимизации. ))
Какие ещё ссылки? У переменных result и someDictionary даже тип не ссылочный)))
V>Но эти ссылки никогда не валидны одновременно, во что тебя уже тыкали.
И дальше что? Операции происходят над объектом, а не «ссылками», а объект в обоих случаях один и тот же.
σ>>— Да какой тут способ, дело не хитрое.
V>Угу, ты пытался рассуждать о неких проблемах.
Это широко известная проблема (в узких кругах)
V>Сформулировать проблему ты не смог
Это ты не смог понять
V>я попытался тебе помочь
Cura te ipsum
V>Давай ты включишь уже моск и попытаешься, таки, сформулировать проблему. V>Можно своими словами, бгг..
Стёкла не выдави своим раздутым ЧСВ
V>От одного сотрясения воздуха абревиатурами RVO/NRVO твои тараканы понятнее не становятся.
От одного сотрясения воздуха словами про "контекст" или "внутренние подробности" твой бред ответом на проблему не становится
Re[90]: Когда это наконец станет defined behavior?
Здравствуйте, σ, Вы писали:
σ>Похоже, у тебя возникли, раз ты утверждаешь, что объекта якобы два.
Согласно семантике — два.
Согласно способу реализации — соптимизировали в один.
V>>Описаны внутренние подробности реализации трюка. σ>Что значит внутренние?
Что и без этой подробности семантика твоей программы не изменится.
V>>Было бы понятно — не задавал бы глупых вопросов. V>>Согласно семантике речь идёт о двух разных объектах и эта семантика гарантируется. σ>Гарантируется, что при NRVO объект один и тот же.
В стандарте с С++17 рекомендуется RV-оптимизация только безымянного объекта, т.е. мой пример под это НЕ попадает.
А для моего примера в стандарте сказано — компилтору разрешается убирать лишнее копирование (или перемещающее копирование).
V>>Не согласен — обоснуй. σ>У тебя возникли проблемы с прочтением?
У тебя возникли проблемы с формулировкой проблемы.
V>>А что эту семантику можно реализовать через ссылку на одну и ту же область памяти в различных точках программы — так в этом и состоит суть RV-оптимизации. )) σ>Какие ещё ссылки? У переменных result и someDictionary даже тип не ссылочный)))
Мда...
Согласно определению, переменная — это адрес объекта.
Переменная-поле — адрес от "начала" объекта.
Глобальная — адрес в глобальном сегмента данных.
Локальная — адрес в локальном фрейме стека.
В общем, ликбез — доступ к полям объектов или автоматическим переменным на стеке всегда косвенный.
Прямой доступ возможен только к глобальным переменным.
V>>Но эти ссылки никогда не валидны одновременно, во что тебя уже тыкали. σ>И дальше что? Операции происходят над объектом, а не «ссылками», а объект в обоих случаях один и тот же.
Операции над объектами происходят через ссылание на них — через имя переменной, либо через явные ссылочные типы данных.
σ>>>— Да какой тут способ, дело не хитрое. V>>Угу, ты пытался рассуждать о неких проблемах. σ>Это широко известная проблема (в узких кругах)
Но сформулировать не можешь?
Так и запишем.
V>>Сформулировать проблему ты не смог σ>Это ты не смог понять
Я пока не видел формулирования, т.е. понимать пока нечего.
Я попытался тебе помочь, но ты там не в состоянии ответить: http://www.rsdn.org/forum/cpp/8582417.1
V>>Давай ты включишь уже моск и попытаешься, таки, сформулировать проблему. V>>Можно своими словами, бгг.. σ>Стёкла не выдави своим раздутым ЧСВ
Чья бы корова мычала. ))
Ты зачем-то начал хамить в банальном, в общем-то, случае.
Я тоже в детстве психовал, когда не сразу что-то понимал... Но так то в детстве! ))
V>>От одного сотрясения воздуха абревиатурами RVO/NRVO твои тараканы понятнее не становятся. σ>От одного сотрясения воздуха словами про "контекст" или "внутренние подробности" твой бред ответом на проблему не становится
Второй раз я дал тебе ссылку, где давно можно было бы ответить по-существу, вместо пререканий.
Здравствуйте, B0FEE664, Вы писали:
BFE>Проблема усугубляется тем, что требования к аллокаторам плохо совместимы с требованиями к placment new (хотя для меня этот вопрос до конца не ясен).
ИМХО, ситуация перезаписи объекта через placement new мало отличается от такой:
const SomeObj * a = new SomeObj(42);
delete a;
const SomeObj * b = new SomeObj(43);
std::cout << a->value();
где a и b имеют одинаковый адрес.
BFE>В целом получается, что есть много старого кода формально с UB и это мешает оптимизации
Оптимизации мешает отсутствие полного знания о жизненном цикле объекта.
Re[90]: Когда это наконец станет defined behavior?
Здравствуйте, σ, Вы писали:
σ>Похоже, у тебя возникли, раз ты утверждаешь, что объекта якобы два.
Это у тебя проблемы с пониманием, если ты не можешь понять по контексту, в каком случае имеется в виду семантика, а в каком — особенности внутренней реализации.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re[91]: Когда это наконец станет defined behavior?
σ>>Похоже, у тебя возникли, раз ты утверждаешь, что объекта якобы два.
V>Согласно семантике — два.
Да нет, согласно семантике — один. Это вполне себе наблюдаемое поведение. Различить, было NRVO или нет — возможно. As-if rule тут не катит. Поэтому стандарт явно оговаривает этот случай.
V>>>Описаны внутренние подробности реализации трюка. σ>>Что значит внутренние?
V>Что и без этой подробности семантика твоей программы не изменится.
Лол)))
Когда объекта два, то в функции объект неконстантный, а вне — константный и всё просто: можно менять в функции и нельзя вне.
Когда объект один в обоих местах, то он либо константный и там и там, либо не там и не там. Если он константный, то его модифицировать его в функции это UB. А если неконстантный, то его можно модифицировать вне функции, это не UB.
Это называется «семантика не изменится»?
V>Оптимизации не являются обязательными. V>Более того, несут с собой некоторые ограничения: V>https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0135r0.html
V>В стандарте с С++17 рекомендуется RV-оптимизация только безымянного объекта, т.е. мой пример под это НЕ попадает.
V>А для моего примера в стандарте сказано — компилтору разрешается убирать лишнее копирование (или перемещающее копирование).
Да, в твоём примере NRVO не наблюдаемо, но сделать его наблюдаемым и задетектить можно.
V>>>А что эту семантику можно реализовать через ссылку на одну и ту же область памяти в различных точках программы — так в этом и состоит суть RV-оптимизации. )) σ>>Какие ещё ссылки? У переменных result и someDictionary даже тип не ссылочный)))
V>Мда... V>Согласно определению, переменная — это адрес объекта.
В стандарте слегка другое определение))) (Впрочем, оно кривое, но правильное всё равно будет другм)
V>Переменная-поле — адрес от "начала" объекта.
Non-static data member по определению не считается/не наывается variable (переменной).
V>Глобальная — адрес в глобальном сегмента данных. V>Локальная — адрес в локальном фрейме стека.
V>В общем, ликбез — доступ к полям объектов или автоматическим переменным на стеке всегда косвенный. V>Прямой доступ возможен только к глобальным переменным.
Так. И как эта простыня текста отвечает на «какие ещё ссылки?»
V>>>Но эти ссылки никогда не валидны одновременно, во что тебя уже тыкали. σ>>И дальше что? Операции происходят над объектом, а не «ссылками», а объект в обоих случаях один и тот же.
V>Операции над объектами происходят через ссылание на них — через имя переменной, либо через явные ссылочные типы данных.
НУ И ДАЛЬШЕ-ТО ЧТО????????????
Константность — это свойство объекта. UB — при модификации константного объекта. Какая разница, сколько где каких ссылок на него, и через какие из них это произойдёт?
σ>>>>— Да какой тут способ, дело не хитрое. V>>>Угу, ты пытался рассуждать о неких проблемах. σ>>Это широко известная проблема (в узких кругах)
V>Но сформулировать не можешь? V>Так и запишем.
Это ты тормозишь на ровном месте. Ладно, попробую ещё раз.
При NRVO переменная, которая инициализируется вызовом функции, и некая переменная внутри этой функции, обозначают один и тот же объект. Только вот может быть так, что снаружи переменная типа const T, а внутри — T. Но тип объекта это отдельная от типов переменной вещь, и раз объект один, то и тип один. Так какой объект — константый или нет?
Re[92]: Когда это наконец станет defined behavior?
Здравствуйте, σ, Вы писали:
V>>Согласно семантике — два. σ>Да нет, согласно семантике — один.
Два.
σ>Это вполне себе наблюдаемое поведение.
В этом суть оптимизации.
Точно такая же происходит здесь:
const SomeObj obj = SomeObj(args);
Согласно семантике, создаётся временный безымянный объект и копируется (либо перемещается) в целевую переменную obj.
Лишнего копирования/перемещения можно избежать.
При возврате по значению применяется ровно та же логика.
σ>Различить, было NRVO или нет — возможно.
Только если конструкторы/деструкторы имеют побочные эффекты.
σ>As-if rule тут не катит. Поэтому стандарт явно оговаривает этот случай.
Объясняет для непонятливых, скорее, почему не надо разбрасываться побочными эффектами в конструторах и деструкторах. ))
σ>Когда объекта два, то в функции объект неконстантный, а вне — константный и всё просто: можно менять в функции и нельзя вне.
Это не принципиально, ровно так же как не принципиально в примере выше при инициализации.
И ты уже порядком поднадоел своей непонятливостью, положа руку на.
Если выражение справа исполняется лишь до тех пор, пока выражение слева является неинициализированным — то какая нахрен польза от твоих спекуляций?
Медитируй над продвижением точки исполнения, пальчиком по экрану поводи, может дойдёт. ))
Ну нельзя в императивной программе рассуждать об одновременности событий из одного потока исполнения.
А ты вот так запросто об этом рассуждаешь.
Позорище, сорри.
Re[91]: Когда это наконец станет defined behavior?
σ>>И во время конструирования в твоём примере объект тоже константный.
V>Каким образом? ))
По определению, которое я линканул. Его ты, видимо, тоже не смог понять
V>Конструктор объекта не имеет понятия — создаёт ли он константный объект или мутабельный.
И? Константный объект или нет зависит от его типа. А не от того, что там понимает конструктор. Объект вообще может не конструктором инициализироваться.
Ты очень много пишешь всяких утверждений, которые вообще непонятно на что влияют. Ты просто любишь своими наблюдениями делиться?
Re[93]: Когда это наконец станет defined behavior?
V>>>Согласно семантике — два. σ>>Да нет, согласно семантике — один.
V>Два.
Симптоматично, что ни одного пруфа от тебя до сих пор не было.
σ>>Это вполне себе наблюдаемое поведение.
V>В этом суть оптимизации. V>Точно такая же происходит здесь: V>
const SomeObj obj = SomeObj(args);
V>Согласно семантике, создаётся временный безымянный объект и копируется (либо перемещается) в целевую переменную obj.
Или не создаётся и не копируется, тоже «согласно семантике», а не «способу реализации»
V>Лишнего копирования/перемещения можно избежать. V>При возврате по значению применяется ровно та же логика.
Только при возврате по значению может быть несколько переменных с разной константностью, обозначающих один и тот же объект. И тогда возникают некоторые вопросы.
σ>>Различить, было NRVO или нет — возможно.
V>Только если конструкторы/деструкторы имеют побочные эффекты.
Не только. Но даже если бы было и только — какая разница?
σ>>As-if rule тут не катит. Поэтому стандарт явно оговаривает этот случай.
V>Объясняет для непонятливых, скорее, почему не надо разбрасываться побочными эффектами в конструторах и деструкторах. ))
Пруф можно?
σ>>Когда объекта два, то в функции объект неконстантный, а вне — константный и всё просто: можно менять в функции и нельзя вне.
V>Это не принципиально, ровно так же как не принципиально в примере выше при инициализации.
Разница между программой без UB и с UB — не принципиальна?
V>И ты уже порядком поднадоел своей непонятливостью, положа руку на.
Забавные проекции.
V>Если выражение справа исполняется лишь до тех пор, пока выражение слева является неинициализированным — то какая нахрен польза от твоих спекуляций?
Здравствуйте, σ, Вы писали:
σ>И? Константный объект или нет зависит от его типа. А не от того, что там понимает конструктор. Объект вообще может не конструктором инициализироваться.
Интересно (правда интересно, здесь нет ни иронии, ни сарказма), а чем кроме конструктора может инициализироваться константный объект?
Вот тупо есть:
const T immutable_value;
Чем его можно проинициализировать кроме как конструктором?
Оно понятно, что в C++23 появился std::start_lifetime_as, посредством которого можно сделать:
Здравствуйте, kov_serg, Вы писали:
_>Здравствуйте, T4r4sB, Вы писали:
TB>>Проверил разные версии кланга, да, он явно продвинутее, чем гцц.
_>Несомненно продвинутее _>https://godbolt.org/z/EY73G4nMr
σ>>И? Константный объект или нет зависит от его типа. А не от того, что там понимает конструктор. Объект вообще может не конструктором инициализироваться.
S>Интересно (правда интересно, здесь нет ни иронии, ни сарказма), а чем кроме конструктора может инициализироваться константный объект?
Действительно, чем же…
const int i = 0;
const struct S { int i; } s = {0};
Re[93]: Когда это наконец станет defined behavior?
Здравствуйте, σ, Вы писали:
σ>>>И? Константный объект или нет зависит от его типа. А не от того, что там понимает конструктор. Объект вообще может не конструктором инициализироваться.
S>>Интересно (правда интересно, здесь нет ни иронии, ни сарказма), а чем кроме конструктора может инициализироваться константный объект?
σ>Действительно, чем же… σ>
const int i = 0;
σ>const struct S { int i; } s = {0};
Хорошо бы понять что здесь есть объект. Надо полагать, что `int i`.