лишнего гемороя и растовских крякозябр для описания владения объектом?
Тогда мне нужна ваша помошь советом, критикой и т.п. https://github.com/apolukhin/apolukhin.github.io/blob/master/papers/reloc_value_proposal.md
Какие там кракозябры для описания владения?)
ну то что работает только для локальных переменных правильно, но нужно удалять дефолтное релоцирование, если нетривиальный мув/копирование, всё что мы хотим реально сделать здесь это управление тем нужно ли вызывать деструктор, при этом важно что это должно быть достижимо для компилятора, возможно специальная функция обозначающая это действие. Type t; std::end_lifetime(t); // аналогично С++23 std::start_lifetime_as Вопросы: что будет если применить это на параметр функции? Что если применить это в switch / if? А что если goto?
> без лишнего гемороя и растовских крякозябр > ключевое слово relocate на 8 символов 🤨
вообще есть версия light когда добавляются трейты is_relocatable и возможно теги, внутри проверяется может ли так случится, что тип селф референс и собственно всё. Дальше добавляются алгоритмы std::relocate и контейнеры начинают ими пользоваться если возможно. Например std::ranges::move(rng, out) если видит, что ренж не borrowed, то может сделать relocate, типа того
Тут серьезный cons это то что компилятор должен будет отслеживать relocation объектов. То есть рядом с каждым локальным потенциально релоцируемым объектом будет ещё флажок. Это утяжелит cleanup стека. Понятно что в любом moved out обычно и так есть уже if, будет double if.
так не будет рантайм иф
if(condition) foo(relocate local);
как достать элемент из вектора?
и где аннотация для метода
я считаю хватит добавления этого только для самых локальных переменных и всё
я про то что у нас методы с & и &&, а методов с relocate нету
это struct X { X foo() { return relocate *this; } };
да, жаль, только что *this это не локал
пожалуй имеет смысл спецификация метода подобная, чтобы компилятор знал об этом
Я ещё может до конца не понял, но это же ломает ABI? Как переложить destructor на callee?
а еще разве у элементов вектора не динамический скоуп, запрещая вектор таких типов?
Это отдельный шаг, end_lifetime попзже. Там очень много подводных камней.
Зато ищется в поисковиках легко )
Да, но с ними не получится нормально передавать объекты в функции и не получится писать non-nullable types
Нет, без флажков, всё на compile time. Подчеркну это в документе
никак. Доставание элемента нарушит инварианты вектора и всё сломается
с элементом в структуре то же самое, выходит?
добавляю, упёрся что нельзя релокейтить из параметров функции без слома ABI
да-да, я про него забыл, исправляюсь
Так и В параметры тоже получается нельзя.
передавать в параметры можно, там RVO работает там тот же принцип
ну я про то что из *this тоже релокейтить нельзя
ага, никак. Иначе напарываемся на частычный деструктор объекта, а эту банку с червями лучше не открывать
Мотивацию для пропозала можно разделить на 2 части. 1. Желание соптимизировать. 2. Желание исключить потенциальный пустой стейт. Оба этих желания понятны, но на мой взгляд предлагаемый relocate - удовлетворяет их очень частично - создает при этом слишком много вопросов, которые в документе вынесены "на потом". Второе желание удовлетворяется сочетанием типов наподобие not_null<T*> и атрибутов -- уже сейчас можно собрать вполне приличный набор атрибутов, собрать в один и стандартизировать. Не говоря уже о в целом неплохих диагностиках в компиляторах и статанализаторах на тему use-after-move. С первым желанием сложнее. Да, было бы хорошо не вызывать деструкторы, если они для moved-from state сводятся к noop. Нужен ли для этого кейворд? Спорно, хотя поддержка со стороны языка так или иначе нужна. Кейворд легко добавить, но с ним потом еще по меньшей мере 20 лет жить. try relocate нагружает кейворд еще и откатом к std::forward -- это сомнительно. Более детальный отзыв постараюсь написать позже, но мне пока не нравится :) Вообще, как мне кажется, подход заглохшего (?) "Беспредельный copy elision" https://github.com/cpp-ru/ideas/issues/256 покрыл бы множество кейсов, затрагиваемых данным PR, причем без использования какого-либо дополнительного синтаксиса. Не все, конечно, и уж совсем не затронул бы релокацию элементов вектора, с которой все началось. Мне также неясен следующий момент: - Деструктор объекта, передаваемого по значению аргументом функции, вызывается caller'ом. - Мы делаем foo(relocate str), "забывая" про деструктор str - caller по какой-то причине не сделал reloc/std::move из аргумента, таким образом не завладев ресурсом. - ??? - Утечка ресурса. Я не увидел в документе заметки о том, что делать в таком случае. Пробежался по P2785R1, какие-то пометки касательно unowned parameter там есть, но ничего по этому кейсу я и там не увидел. Где я не прав?
Нда, идея прям на руках рассыпается
эх ещё бы разрешить компилятору последнее использование переменной превращать в мув и улучшить тонну кода где забыли / никогда не было мува
Так уже частично сделали: implicitly-movable-entities, которым категория выправляется в return/throw-контекстах.
Если ты помнишь, я расписывал две возможные ветки реализации и обнаружил, что надо просто принять [[1144]] Могу поднять логи
Да-да. Но я в комитете не один, нужно чтобы большинство смирилось)
Когда вызовется деструктор в случае conditional relocate? Хотелось бы конечно чтобы решал компилятор. Но наверняка предлагается вариант где соблюдается обычный порядок. Это добавляет кондишенов. Ещё это довольно плохо совмещается с тем что большинство деструкторов уже conditional в отличие от того же раста. То есть получается разработчик должен будет думать когда лучше написать relocate, а когда move :(
тут ничего про компилятор нет вовсе, это вручную вызов деструктора
А блумберги хотят это просто свойством типа сделать? Вроде ж есть резон.
A a; if (runtime_flag) { foo(relocate a); } bar(); Деструктор a будет вызван после или до вызова bar, в случае если runtime_flag будет false?
Да не обойдется там без флагов. foo(mayTrowX(), relocate Y, mayThrowZ())
Вообще жалко в раст не завезли early drop
Это огромный недостаток комитета
Обсуждают сегодня