#опытным
Сегодня рассмотрим функцию-хэлпер, которая поможет нам в рассмотрении одного из юзкейсов применимости deduction this. Их одновременное введение в 23-й стандарт логично, хэлпер дополняет и расширяет применимость deducing this.
Эта функция очень похожа на std::move и, особенно, на std::forward. Она потенциально аффектит только ссылочность типа и может добавлять константности.
Если std::forward объявлена так
template< class T >
constexpr T&& forward(std::remove_reference_t<T>& t ) noexcept;
template< class T >
constexpr T&& forward(std::remove_reference_t<T>&& t ) noexcept;
За счет перегрузок для lvalue и rvalue, она позволяет правильно передавать тип параметра, объявленного универсальной ссылкой, во внутренние вызовы. Здесь задействован всего один шаблонный параметр.
std::forward_like делает шаг вперед. Функция позволяет выполнять идеальную передачу данных на основе типа другого выражения.
template< class T, class U >
constexpr auto&& forward_like( U&& x ) noexcept;
Заметьте, что здесь 2 шаблонных параметра. Мы будем кастить x к ссылочному типу параметра Т.
Зачем вообще так делать?
Без deduction this особо незачем. Но вместе с ним мы можем на основе типа объекта, на котором вызывается метод, идеально передавать данные наружу.
Раньше это было возможно только если бы мы возвращали мемберы объекта. На С++20 это выглядело так:
return forward<decltype(obj)>(obj).member;
Это работало с кучей ограничений. Но с появлением deducing this мы можем делать так:
struct adapter {
std::deque<std::string> container;
auto&& operator[](this auto&& self, size_t i) {
return std::forward_like<decltype(self)>(self.container[i]);
} };Мы можем из оператора индексации вернуть правую ссылку на строку внутри container, если мы вызываем оператор на правоссылочном объекте. В таком случае объект нам больше не нужен и нет смысла сохранять все его данные. Поэтому можно мувать наружу содержимое контейнера. Ну а если объект адаптера обычный lvalue и не собирается разрушаться, то возвращаем левую ссылку на элемент контейнера.
Более того, с помощью такого приема вообще в принципе появляется возможность использования оператора индексации на rvalue объектах. Если вернуть левую ссылку на содержимое временного объекта, то получим висячую ссылку и UB.
В общем, эта функция разрешает вот такие оптимизации и унифицирует интерфейс для объектов разной ссылочности.
Follow the head. Stay cool.
#cpp23 #template