пример реализации add_lvalue_reference - PullRequest
2 голосов
/ 22 декабря 2019

При поиске std::add_lvalue_reference в cppreference можно увидеть следующий пример реализации:

namespace detail {

template <class T>
struct type_identity { using type = T; }; // or use std::type_identity (since C++20)

template <class T>
auto try_add_lvalue_reference(int) -> type_identity<T&>;
template <class T>
auto try_add_lvalue_reference(...) -> type_identity<T>;

} // namespace detail

template <class T>
struct add_lvalue_reference : decltype(detail::try_add_lvalue_reference<T>(0)) {};

Зачем нужен второй try_add_lvalue_reference и в каких случаях это будетназывается вместо первого?

1 Ответ

0 голосов
/ 22 декабря 2019

Вторая перегрузка выполняет условие «Иначе» в определении, заданном в cppreference :

1) Если T - это тип функции, который не имеет cv- илиref-определитель или тип объекта, предоставляет тип-члена-члена typedef, который является T &. Если T является rvalue ссылкой на некоторый тип U, тогда тип - U &. В противном случае типом является T.

Рассмотрим, например:

using T = void() const; // Function type with const qualifier
using U = add_lvalue_reference<T>::type;

В соответствии с определением у нас должно быть U == T, но если у нас нет второй перегрузки шаблона, тогда этот код вызовет ошибку во время компиляции:

Невозможно сформировать ссылки на cv- или ref-квалифицированные типы функций, и поэтому первая перегрузка шаблона try_add_lvalue_reference исключена SFINAE.

Если есть только эта перегрузка, вызов detail::try_add_lvalue_reference<T>(0) вызывает сбой, потому что нет жизнеспособной перегрузки.

Вторая перегрузка не пытается сформировать ссылку на квалифицированный const тип функции ипоэтому всегда жизнеспособен и будет выбран, если первый не вернет, возвращая сам тип.

Параметры int и ... гарантируют, что обе перегрузки могут быть вызваны с аргументом int и... имеет дополнительное преимущество: он всегда имеет более низкий приоритет при разрешении перегрузки. Поэтому, если обе перегрузки шаблона являются жизнеспособными, будет выбран первый, чтобы обеспечить тип с добавленной ссылкой lvalue, где это возможно.

...