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> 是U
加上Ti
的 cv 和引用限定符,则成员类型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 类型的定义(如上面使用的那些),请参见条件运算符。
目录 |
[编辑] 成员类型
名称 | 定义 |
type
|
所有 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 的共同引用类型(类模板特化) |
[编辑] 注释
特性测试 宏 | 值 | 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) |
指定两种类型共享一个共同引用类型 (概念) |