std::common_reference
定義於標頭檔案 <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` 格式良好
- 令型別 `S` 為 `T1` 和 `T2` 的*簡單公共引用型別*(如下定義)。如果滿足以下所有條件,成員型別 `type` 命名 `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>::type 和 std::basic_common_reference<U, T, UQual, TQual>::type 必須表示相同的型別。
程式不得特化 `basic_common_reference` 的第三或第四個引數,也不得特化 `common_reference` 本身。違反這些規則新增特化的程式具有未定義行為。
標準庫提供了 `basic_common_reference` 的以下特化:
確定兩個 pair 的公共引用型別(類模板特化) | |
確定 tuple 和 tuple-like 型別的通用引用型別(類模板特化) | |
確定 `reference_wrapper` 和非 `reference_wrapper` 的公共引用型別 (類模板特化) |
[編輯] 注意
特性測試宏 | 值 | 標準 | 特性 |
---|---|---|---|
__cpp_lib_common_reference |
202302L |
(C++23) | 將 std::reference_wrapper 的 std::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() {}
[編輯] 另請參閱
(C++11) |
確定一組型別的公共型別 (類模板) |
(C++20) |
指定兩種型別共享一個共同的引用型別 (概念) |