std::add_lvalue_reference, std::add_rvalue_reference
Материал из cppreference.com
Определено в заголовочном файле <type_traits>
|
||
template< class T > struct add_lvalue_reference; |
(1) | (начиная с C++11) |
template< class T > struct add_rvalue_reference; |
(2) | (начиная с C++11) |
Создаёт левостороннюю или правостороннюю ссылку на тип T
.
1) Если T является функциональным типом, который не имеет cv- или ref-квалификатора, или объектным типом, предоставляет typedef элемент type, который равен T&. Если T является ссылкой rvalue на некоторый тип U, то type является U&. Иначе type равно T.
2) Если T является функциональным типом, который не имеет cv- или ref-квалификатора, или объектным типом, предоставляет typedef элемент type, который равен T&&, иначе type равно T.
Поведение программы, добавляющей специализации для любых шаблонов, описанных на этой странице не определено.
Содержание |
[править] Типы-элементы
Имя | Определение |
type
|
ссылка на T , или T , если ссылку создать нельзя
|
[править] Вспомогательные типы
template< class T > using add_lvalue_reference_t = typename add_lvalue_reference<T>::type; |
(начиная с C++14) | |
template< class T > using add_rvalue_reference_t = typename add_rvalue_reference<T>::type; |
(начиная с C++14) | |
[править] Примечание
Эти преобразования типов учитывают правила очистки ссылки:
- std::add_lvalue_reference<T&>::type равно T&
- std::add_lvalue_reference<T&&>::type равно T&
- std::add_rvalue_reference<T&>::type равно T&
- std::add_rvalue_reference<T&&>::type равно T&&
Основное отличие от прямого использования T& заключается в том, что std::add_lvalue_reference<void>::type равно void, а void& приводит к ошибке компиляции.
[править] Возможная реализация
namespace detail { template <class T> // или используйте std::type_identity (начиная с C++20) struct type_identity { using type = T; }; template <class T> // Обратите внимание, что `cv void&` это ошибка подстановки auto try_add_lvalue_reference(int) -> type_identity<T&>; template <class T> // Обрабатывает T = cv void случай auto try_add_lvalue_reference(...) -> type_identity<T>; template <class T> auto try_add_rvalue_reference(int) -> type_identity<T&&>; template <class T> auto try_add_rvalue_reference(...) -> type_identity<T>; } // namespace detail template <class T> struct add_lvalue_reference : decltype(detail::try_add_lvalue_reference<T>(0)) {}; template <class T> struct add_rvalue_reference : decltype(detail::try_add_rvalue_reference<T>(0)) {}; |
[править] Пример
Запустить этот код
#include <type_traits> int main() { using non_ref = int; using l_ref = typename std::add_lvalue_reference_t<non_ref>; using r_ref = typename std::add_rvalue_reference_t<non_ref>; using void_ref = std::add_lvalue_reference_t<void>; static_assert ( std::is_lvalue_reference_v<non_ref> == false && std::is_lvalue_reference_v<l_ref> == true && std::is_rvalue_reference_v<r_ref> == true && std::is_reference_v<void_ref> == false ); }
[править] Отчёты о дефектах
Следующие изменения поведения были применены с обратной силой к ранее опубликованным стандартам C++:
Номер | Применён | Поведение в стандарте | Корректное поведение |
---|---|---|---|
LWG 2101 | c++11 | Эти свойства преобразования были необходимы для создания ссылок на cv/ref квалифицированные функциональные типы. |
Сами создают cv/ref квалифицированные функциональные типы. |
[править] Смотрите также
(C++11) |
проверяет, является ли тип либо левосторонней ссылкой, либо правосторонней ссылкой (шаблон класса) |
(C++11) |
удаляет ссылку из данного типа (шаблон класса) |
(C++20) |
объединяет std::remove_cv и std::remove_reference (шаблон класса) |