Кратко
Предлагается добавить в стандарт функцию, которая бы позволяла принудительно завершать время жизни локальной переменной, делая её недоступной для дальнейшего использования. Также предлагается реализовать copy elision (или его аналог) для xvalues вида const T&&.
Проблема
На данный момент в C++ нет возможности убрать из скоупа переменную. В лучше случае, мы можем сделать std::move, который оставит после себя обнулённый (в зависимости от определения) объект.
Пример:
{
std::shared_ptr< Some > local_variable = std::make_shared< Some >(...);
...
some_function(std::move(local_variable));
...
local_variable->some_method(); // runtime (!) error
}
Предложение
Добавить функцию - пусть это будет, например, std::drop, - которая бы возвращала по аналогии с std::movexvalue expression, но при этом бы гарантировала ошибку компиляции в случае повтороного доступа к переменной. Тогда пример выше можно было бы написать следующим образом:
{
/* [const] */ std::shared_ptr< Some > local_variable = std::make_shared< Some >(...);
...
some_function(std::drop(local_variable)); // тут переменная "перемещается в функцию" `some_function`, но удаляется из локального скоупа
...
// local_variable->some_method(); // _compile_ time (!) error: "local_variable was dropped before at line ..."
// auto local_variable{}; // _compile_ time (!) error - переопределение должно быть запрещено
// decltype(local_variable) new_variable{}; // _compile_ time (!) error - такое тоже, вероятно, стоит запретить
}
Если сделать переменную local_variable константной, то std::move теряет свой смысл (константная переменная должна "обнулиться", что явно не самый ожидаемый результат), а вот std::drop остаётся актуальной - нет смысла заботиться о константности переменной, удалённой из скоупа. То есть функция std::drop должна либо преобразовывать const T&& в T&&, либо реализовать copy elision. Последний вариант кажется более удачным.
Ещё один пример для дискуссии:
{
std::shared_ptr< Some > local_variable = std::make_shared< Some >(...);
...
// использование std::drop внутри условных операторов тоже стоит запретить. Как и внутри `switch .. case` и `try ... catch`.
/*
if (is_drop) {
std::drop(local_variable);
}
*/
// Использование функции вместе с её аргументом в тех случаях, когда порядок вычисления не определён, не допускается
// some_function(std::drop(local_variable), local_variable);
...
// а вот такое, возможно, стоит разрешить
if constexpr (constexpr_is_drop) {
std::drop(local_variable);
}
}
Тут всё просто: сообщение, которое:
а) Константно. Если мы создали сообщение (например, с помощью статического метода класса Message), то оно не должно меняться.
б) Существует в единственном экземпляре, для чего мы запретили конструктор копирования.
в) Не может быть пустым, для чего мы запретили конструктор и оператор перемещения и конструктор по умолчанию.
Пусть мы хотим после этого определить следующий тип:
Ошибки компиляции логичны, иначе нарушались бы гарантии константности. Но с функцией std::drop можно было бы реализовать перемещение констант.
Предложение суммарно:
1) Добавить функцию, позволяющую удалять локальные переменные из скоупа.
2) Реализовать copy elision (или его аналог) для xvalues вида const T&& (с учётом случаев первого пункта).
Плюсы:
1) Появляется возможность сделать код более понятным и безопасным
2) Расширяются возможности при работе с константами
3) Добавляются подсказки для компиляторов/статических анализаторов
Минусы:
1) Возможно, чтобы разделить временные объекты и перемещаемые константы, придётся добавлять новый тип выражений (?)
? ...
Обратная совместимость.
Реализация функции std::drop не нарушает обратную совместимость. Расширение copy elision для xvalues вида const T&& может нарушить обратную совместимость, если не будет привязано к использованию функции std::drop.
Кратко Предлагается добавить в стандарт функцию, которая бы позволяла принудительно завершать время жизни локальной переменной, делая её недоступной для дальнейшего использования. Также предлагается реализовать copy elision (или его аналог) для xvalues вида
const T&&
.Проблема На данный момент в C++ нет возможности убрать из скоупа переменную. В лучше случае, мы можем сделать
std::move
, который оставит после себя обнулённый (в зависимости от определения) объект. Пример:Предложение Добавить функцию - пусть это будет, например,
std::drop
, - которая бы возвращала по аналогии сstd::move
xvalue expression, но при этом бы гарантировала ошибку компиляции в случае повтороного доступа к переменной. Тогда пример выше можно было бы написать следующим образом:Если сделать переменную
local_variable
константной, тоstd::move
теряет свой смысл (константная переменная должна "обнулиться", что явно не самый ожидаемый результат), а вотstd::drop
остаётся актуальной - нет смысла заботиться о константности переменной, удалённой из скоупа. То есть функцияstd::drop
должна либо преобразовыватьconst T&&
вT&&
, либо реализовать copy elision. Последний вариант кажется более удачным. Ещё один пример для дискуссии:Ещё пример. Рассмотрим следующую структуру:
Тут всё просто: сообщение, которое: а) Константно. Если мы создали сообщение (например, с помощью статического метода класса
Message
), то оно не должно меняться. б) Существует в единственном экземпляре, для чего мы запретили конструктор копирования. в) Не может быть пустым, для чего мы запретили конструктор и оператор перемещения и конструктор по умолчанию.Пусть мы хотим после этого определить следующий тип:
Ошибки компиляции логичны, иначе нарушались бы гарантии константности. Но с функцией
std::drop
можно было бы реализовать перемещение констант.Предложение суммарно: 1) Добавить функцию, позволяющую удалять локальные переменные из скоупа. 2) Реализовать copy elision (или его аналог) для xvalues вида
const T&&
(с учётом случаев первого пункта).Плюсы: 1) Появляется возможность сделать код более понятным и безопасным 2) Расширяются возможности при работе с константами 3) Добавляются подсказки для компиляторов/статических анализаторов
Минусы: 1) Возможно, чтобы разделить временные объекты и перемещаемые константы, придётся добавлять новый тип выражений (?) ? ...
Обратная совместимость. Реализация функции
std::drop
не нарушает обратную совместимость. Расширение copy elision для xvalues видаconst T&&
может нарушить обратную совместимость, если не будет привязано к использованию функцииstd::drop
.