std::add_lvalue_reference, std::add_rvalue_reference — cppreference.com
Материал из cppreference.com
<tbody> </tbody>
| Определено в заголовочном файле |
||
|
|
(1) | (начиная с C++11) |
|
|
(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, если ссылку создать нельзя
|
Вспомогательные типы
<tbody> </tbody>
|
|
(начиная с C++14) | |
|
|
(начиная с 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 квалифицированные функциональные типы. |