名稱空間
變體
操作

std::common_reference

來自 cppreference.com
< cpp‎ | 型別
 
 
超程式設計庫
型別特性
型別類別
(C++11)
(C++11)(DR*)
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
(C++11) 
(C++11)
(C++11)
型別屬性
(C++11)
(C++11)
(C++14)
(C++11)(C++26 中已棄用)
(C++11)(直到 C++20*)
(C++11)(C++20 中已棄用)
(C++11)
型別特性常量
元函式
(C++17)
支援的操作
關係與屬性查詢
型別修改
(C++11)(C++11)(C++11)
型別轉換
(C++11)(C++23 中已棄用)
(C++11)(C++23 中已棄用)
(C++11)
(C++11)(直到 C++20*)(C++17)

common_reference
(C++20)
(C++11)
(C++17)
編譯時有理數算術
編譯時整數序列
 
定義於標頭檔案 <type_traits>
template< class... T >
struct common_reference;
(C++20 起)

確定型別 `T...` 的公共引用型別,即 `T...` 中的所有型別都可以轉換或繫結到的型別。如果存在這樣的型別(根據以下規則確定),則成員 `type` 命名該型別。否則,不存在成員 `type`。如果 `T...` 中的任何型別是不完整型別(除了可能帶 cv 限定符的 `void`),則行為是未定義的。

當給定引用型別時,`common_reference` 嘗試查詢一個引用型別,所有提供的引用型別都可以繫結到該引用型別,但如果找不到這樣的引用型別,則可能返回非引用型別。

  • 如果 sizeof...(T) 為零,則沒有成員 `type`。
  • 如果 sizeof...(T) 為一(即 `T...` 只包含一種型別 `T0`),則成員 `type` 命名與 T0 相同的型別。
  • 如果 sizeof...(T) 為二(即 `T...` 包含兩種型別 `T1` 和 `T2`)
    • 令型別 `S` 為 `T1` 和 `T2` 的*簡單公共引用型別*(如下定義)。如果滿足以下所有條件,成員型別 `type` 命名 `S`
      • `T1` 和 `T2` 都是引用型別
      • `S` 格式良好
(C++23 起)
  • 否則,如果 std::basic_common_reference<std::remove_cvref_t<T1>, std::remove_cvref_t<T2>, T1Q, T2Q>::type 存在,其中 `TiQ` 是一個一元別名模板,使得 TiQ<U> 是 `U` 加上 `Ti` 的 cv 限定符和引用限定符,則成員型別 `type` 命名該型別;
    • 否則,如果 decltype(false? val<T1>() : val<T2>()),其中 `val` 是函式模板 template<class T> T val();,是一個有效型別,則成員型別 `type` 命名該型別;
    • 否則,如果 std::common_type_t<T1, T2> 是一個有效型別,則成員型別 `type` 命名該型別;
    • 否則,不存在成員 `type`。
  • 如果 sizeof...(T) 大於二(即 `T...` 由型別 `T1, T2, R...` 組成),那麼如果 std::common_reference_t<T1, T2> 存在,則成員 `type` 表示 std::common_reference_t<std::common_reference_t<T1, T2>, R...>,如果這樣的型別存在。在所有其他情況下,不存在成員 `type`。

兩個引用型別 `T1` 和 `T2` 的*簡單公共引用型別*定義如下:

  • 如果 `T1` 是 `cv1 X&` 且 `T2` 是 `cv2 Y&`(即,兩者都是左值引用型別):它們的簡單公共引用型別是 decltype(false? std::declval<cv12 X&>() : std::declval<cv12 Y&>()),其中 *cv12* 是 *cv1* 和 *cv2* 的並集,如果該型別存在且是引用型別;
  • 如果 `T1` 和 `T2` 都是右值引用型別:如果 `T1&` 和 `T2&` 的簡單公共引用型別(根據上一條確定)存在,則令 `C` 表示該型別對應的右值引用型別。如果 std::is_convertible_v<T1, C>std::is_convertible_v<T2, C> 都為 true,則 `T1` 和 `T2` 的簡單公共引用型別是 `C`;
  • 否則,兩種型別之一必須是左值引用型別 `A&`,另一種必須是右值引用型別 `B&&`(`A` 和 `B` 可能帶 cv 限定符)。令 `D` 表示 A&B const& 的簡單公共引用型別(如果有)。如果 D 存在且 std::is_convertible_v<B&&, D>true,則簡單公共引用型別是 `D`;
  • 否則,沒有簡單公共引用型別。

請參閱 條件運算子,瞭解像上面使用的表示式 false ? X : Y 型別的定義。

目錄

[編輯] 成員型別

名稱 定義
型別 所有 `T...` 的公共引用型別

[編輯] 輔助型別

template< class... T >
using common_reference_t = std::common_reference<T...>::type;
template< class T, class U, template<class> class TQual, template<class> class UQual >
struct basic_common_reference {};

類模板 `basic_common_reference` 是一個定製點,允許使用者影響 `common_reference` 對於使用者定義型別(通常是代理引用)的結果。主模板是空的。

[編輯] 特化

如果 std::is_same_v<T, std::decay_t<T>>std::is_same_v<U, std::decay_t<U>> 都為 true,並且其中至少一個依賴於程式定義型別,則程式可以針對前兩個引數 `T` 和 `U` 對 std::basic_common_reference<T, U, TQual, UQual> 進行特化。

如果這樣的特化具有名為 `type` 的成員,則它必須是一個公共且明確的成員,命名一種型別,使得 TQual<T>UQual<U> 都可以轉換為該型別。此外,std::basic_common_reference<T, U, TQual, UQual>::typestd::basic_common_reference<U, T, UQual, TQual>::type 必須表示相同的型別。

程式不得特化 `basic_common_reference` 的第三或第四個引數,也不得特化 `common_reference` 本身。違反這些規則新增特化的程式具有未定義行為。

標準庫提供了 `basic_common_reference` 的以下特化:

確定兩個 pair 的公共引用型別
(類模板特化) [編輯]
確定 tupletuple-like 型別的通用引用型別
(類模板特化) [編輯]
確定 `reference_wrapper` 和非 `reference_wrapper` 的公共引用型別
(類模板特化) [編輯]

[編輯] 注意

特性測試 標準 特性
__cpp_lib_common_reference 202302L (C++23) std::reference_wrapperstd::common_reference_t 設為引用型別

[編輯] 示例

#include <concepts>
#include <type_traits>
 
static_assert(
    std::same_as<
        int&,
        std::common_reference_t<
            std::add_lvalue_reference_t<int>,
            std::add_lvalue_reference_t<int>&,
            std::add_lvalue_reference_t<int>&&,
            std::add_lvalue_reference_t<int>const,
            std::add_lvalue_reference_t<int>const&
        >
    >
);
 
int main() {}

[編輯] 另請參閱

確定一組型別的公共型別
(類模板) [編輯]
指定兩種型別共享一個共同的引用型別
(概念) [編輯]