You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Вся суть проблемы с релоцированием объектов заключается в том, что компилятору неизвестно каким образом происходит мув и из кода невозможно узнать (помимо trivial мува) каково поведение типа.
Но если посмотреть на проблему шире, оказывается, что валидных стратегий реализации мув конструктора всего 4:
memcpy (trivial move)
exchange с дефолтным состоянием
self reference сценарий
у объекта вовсе нет мува, а есть только копирование(С++03 объект)
ну или тип вообще не movable, но очевидно его и релоцировать нельзя
Так вот, сейчас в С++ представлен только первый тип как = default и трейт is_trivially_move_constructible,
Я предлагаю
добавить сценарий 2 как стратегию поведения на муве и трейты для этого, например
Type(Type&&) = default; // то что сейчас, мув конструктор у всех филдов/базовых классов
Type(Type&&) = swap; // дефолтное конструирование + вызов swap через adl для всех филдов и базовых классов
То же самое можно сделать с оператором
Type& operator=(Type&&) = swap; // типичная реализация мув оператора
и добавить трейт is_not_self_reference который будет давать true если у типа и рекурсивно у всех типов за ним нет нетривиальных мувов.
Т.к. фактически нет никакого смысла делать нетривиальный мув при таких условиях
Это
уберёт бойлерплейт
позволит компилятору и контейнерам узнавать практически во всех случаях, что тип не селф референс
Более того, практически все дефолтные конструкторы и деструкторы можно сделать constexpr, даже у std::any такой конструктор.
компилятор может "выдумать" объект и дефолтно его сконструировать, а потом разрушить и на компиляции узнать, что деструктор был noop.
Для этого я предлагаю ещё один трейт is_trivially_destructible_after_move
The text was updated successfully, but these errors were encountered:
std::is_trivially_relocatable помоему направлен на решение тойже проблемы другим путем cplusplus/papers#43
я прекрасно знаю об этом и многих других пропозалах, их проблема в том, что они не помогают компилятору ничего вывести и не уменьшают количество нужного кода, а лишь увеличивают.
Например, нужно будет аттрибутом или ещё как то помечать типы тривиальные для релоцирования, к тому же нет ничего что уже сейчас бы не было доступно, т.е. прямо сейчас вы можете сделать using relocatable = int; внутри типа, потом в алгоритмах это проверять. Это будет надёжнее аттрибута. Короче говоря усложнение языка без профитов
Моё предложение делает эту работу за программиста и позволяет старому коду стать лучше, иногда с минимальными изменениями типа = swap, позволит компилятору вовсе не генерировать мув конструкторы и т.д.
И если говорить про трейт is_trviially_destructible_after_move я считаю это первый шаг к тому чтобы статически доказывать семантические утверждения про типы, то чего так хотел Страуструп.
Вся суть проблемы с релоцированием объектов заключается в том, что компилятору неизвестно каким образом происходит мув и из кода невозможно узнать (помимо trivial мува) каково поведение типа.
Но если посмотреть на проблему шире, оказывается, что валидных стратегий реализации мув конструктора всего 4:
ну или тип вообще не movable, но очевидно его и релоцировать нельзя
Так вот, сейчас в С++ представлен только первый тип как = default и трейт is_trivially_move_constructible,
Я предлагаю
добавить сценарий 2 как стратегию поведения на муве и трейты для этого, например
Type(Type&&) = default; // то что сейчас, мув конструктор у всех филдов/базовых классов
Type(Type&&) = swap; // дефолтное конструирование + вызов swap через adl для всех филдов и базовых классов
То же самое можно сделать с оператором
Type& operator=(Type&&) = swap; // типичная реализация мув оператора
и добавить трейт is_not_self_reference который будет давать true если у типа и рекурсивно у всех типов за ним нет нетривиальных мувов.
Т.к. фактически нет никакого смысла делать нетривиальный мув при таких условиях
Это
Более того, практически все дефолтные конструкторы и деструкторы можно сделать constexpr, даже у std::any такой конструктор.
компилятор может "выдумать" объект и дефолтно его сконструировать, а потом разрушить и на компиляции узнать, что деструктор был noop.
Для этого я предлагаю ещё один трейт is_trivially_destructible_after_move
The text was updated successfully, but these errors were encountered: