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
是格式良好的
-
- 假设类型
|
(自 C++23 起) |
- 否则,如果 std::basic_common_reference<std::remove_cvref_t<T1>, std::remove_cvref_t<T2>, T1Q, T2Q>::type 存在,其中
TiQ
是一个一元别名模板,使得 TiQ<U> 是添加了Ti
的 cv 和引用限定符的U
,则成员类型type
将命名该类型;
- 否则,如果 std::basic_common_reference<std::remove_cvref_t<T1>, std::remove_cvref_t<T2>, T1Q, T2Q>::type 存在,其中
- 否则,如果 decltype(false? val<T1>() : val<T2>()) 是有效类型,其中
val
是函数模板 template<class T> T val();,则成员类型type
将命名该类型; - 否则,如果 std::common_type_t<T1, T2> 是有效类型,则成员类型
type
将命名该类型; - 否则,不存在成员
type
。
- 否则,如果 decltype(false? val<T1>() : val<T2>()) 是有效类型,其中
- 如果 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
的结果。主要模板为空。
[编辑] 特化
程序可以对前两个参数 T
和 U
特化 std::basic_common_reference<T, U, TQual, UQual>,如果 std::is_same_v<T, std::decay_t<T>> 和 std::is_same_v<U, std::decay_t<U>> 都是 true,并且至少其中一个依赖于程序定义的类型。
如果这种特化有一个名为 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 的公共引用类型(类模板特化) |
[编辑] 注释
特性测试 宏 | 值 | Std | 特性 |
---|---|---|---|
__cpp_lib_common_reference |
202302L | (C++23) | 使 std::common_reference_t 的 std::reference_wrapper 成为一个引用类型 |
[编辑] 示例
#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) |
指定两种类型共享一个公共引用类型 (概念) |