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 或引用限定符的函數類型,或者是一個對象類型,則提供成員 typedef type,其類型為 T&。如果 T 是某個類型 U 的右值引用,則 typeU&。否則,typeT
2) 如果 T 是一個沒有 cv 或引用限定符的函數類型,或者是一個對象類型,則提供成員 typedef type,其類型為 T&&,否則 typeT

如果程序添加了此頁面上描述的任何模板的特化,那麼行為未定義。

成員類型

名字 定義
type T 的引用,或當「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&>::typeT&
  • std::add_lvalue_reference<T&&>::typeT&
  • std::add_rvalue_reference<T&>::typeT&
  • std::add_rvalue_reference<T&&>::typeT&&

使用這些類型特徵與直接使用 T& 的主要區別是 std::add_lvalue_reference<void>::typevoid,而 void& 會導致編譯錯誤。

可能的實現

namespace detail
{
    template<class T>
    struct type_identity { using type = T; }; // 或者使用 std::type_identity(C++20 起)

    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>;
    static_assert(std::is_lvalue_reference_v<l_ref>);

    using r_ref = typename std::add_rvalue_reference_t<non_ref>;
    static_assert(std::is_rvalue_reference_v<r_ref>);

    using void_ref = std::add_lvalue_reference_t<void>;
    static_assert(!std::is_reference_v<void_ref>);
}

缺陷報告

下列更改行為的缺陷報告追溯地應用於以前出版的 C++ 標準。

缺陷報告 應用於 出版時的行為 正確行為
LWG 2101 C++11 規定這些變換特徵
產生對 cv/引用限定的函數類型的引用。
產生 cv/引用限定的函數類型自身。

參閱

檢查類型是否為左值引用 或右值引用
(類模板) [編輯]
從給定類型移除引用
(類模板) [編輯]
std::remove_cvstd::remove_reference 結合
(類模板) [編輯]