◐ Shell
clean mode source ↗

std::add_lvalue_reference, std::add_rvalue_reference — cppreference.com

Материал из cppreference.com

<tbody> </tbody>

Определено в заголовочном файле <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, если ссылку создать нельзя

Вспомогательные типы

<tbody> </tbody>

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 квалифицированные
функциональные типы.

Смотрите также