# std::add_lvalue_reference, std::add_rvalue_reference

< cpp‎ | types

定义于头文件 `<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 或引用限定符的函数类型，则提供成员 typedef `type` ，其为 `T&` 。若 `T` 是到某类型 `U` 的右值引用，则 `type` 为 `U&` 。否则， `type` 为 `T` 。
2) 若 `T` 是对象或无 cv 或引用限定符的函数类型，则提供成员 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>
    struct type_identity { using type = T; }; // 或使用 std::type_identity (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>;

    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 <iostream>
    #include <type_traits>

    int main() {
       using nonref = int;
       using lref = typename std::add_lvalue_reference<nonref>::type;
       using rref = typename std::add_rvalue_reference<nonref>::type;

       std::cout << std::boolalpha;
       std::cout << std::is_lvalue_reference<nonref>::value << '\n';
       std::cout << std::is_lvalue_reference<lref>::value << '\n';
       std::cout << std::is_rvalue_reference<rref>::value << '\n';
    }

输出：

    false
    true
    true

### 缺陷报告

下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。

DR | 应用于 | 出版时的行为 | 正确行为
--- | --- | --- | ---
LWG 2101 | C++11 | 曾要求这些变换特性产生到 cv 或引用限定的函数类型的引用。 | 产生 cv 或引用限定的函数类型自身。

### 参阅

is_reference (C++11) | 检查类型是否为左值引用或右值引用 (类模板)
remove_reference (C++11) | 从给定类型移除引用 (类模板)
remove_cvref (C++20) | 将 std::remove_cv 与 std::remove_reference 结合 (类模板)