std:: disjunction
|
定义于头文件
<type_traits>
|
||
|
template
<
class
...
B
>
struct disjunction ; |
(C++17 起) | |
形成类型特性 B... 的 逻辑析取 ,实质上对特性序列执行逻辑或运算。
特化 std :: disjunction < B1, ..., BN > 具有一个公开且无歧义的基类,该基类是
- 如果 sizeof... ( B ) == 0 ,则为 std:: false_type ;否则
-
在
B1, ..., BN中第一个满足 bool ( Bi :: value ) == true 的类型Bi,若不存在此类类型则为BN。
基类成员名称(除
disjunction
和
operator=
外)不会被隐藏,且在
disjunction
中可无歧义地访问。
析取操作具有短路特性:如果存在模板类型参数
Bi
满足
bool
(
Bi
::
value
)
!
=
false
,则实例化
disjunction
<
B1, ..., BN
>
::
value
时不需要对
j > i
的
Bj
::
value
进行实例化。
如果程序为
std::disjunction
或
std::disjunction_v
添加特化,则行为未定义。
目录 |
模板参数
| B... | - |
每个实例化的模板参数
Bi
必须满足:能作为基类使用,且定义的成员
value
可转换为
bool
类型
|
辅助变量模板
|
template
<
class
...
B
>
constexpr bool disjunction_v = disjunction < B... > :: value ; |
(C++17 起) | |
可能的实现
template<class...> struct disjunction : std::false_type {}; template<class B1> struct disjunction<B1> : B1 {}; template<class B1, class... Bn> struct disjunction<B1, Bn...> : std::conditional_t<bool(B1::value), B1, disjunction<Bn...>> {}; |
注释
disjunction
的特化并不必然继承自
std::
true_type
或
std::
false_type
:它仅继承自第一个
B
类型(其
::value
经显式转换为
bool
后为
true
),或当所有类型均转换为
false
时继承自最后一个
B
。例如,
std
::
disjunction
<
std::
integral_constant
<
int
,
2
>
,
std::
integral_constant
<
int
,
4
>>
::
value
的值是
2
。
短路实例化将
disjunction
与
折叠表达式
区分开来:类似
(
...
||
Bs
::
value
)
的折叠表达式会实例化
Bs
中的每个
B
,而
std
::
disjunction_v
<
Bs...
>
会在值可确定时立即停止实例化。当后续类型实例化成本高昂或使用错误类型实例化会导致硬错误时,这一特性尤为有用。
| 功能测试 宏 | 值 | 标准 | 功能 |
|---|---|---|---|
__cpp_lib_logical_traits
|
201510L
|
(C++17) | 逻辑运算符类型特征 |
示例
#include <cstdint> #include <string> #include <type_traits> // values_equal<a, b, T>::value 当且仅当 a == b 时为 true template<auto V1, decltype(V1) V2, typename T> struct values_equal : std::bool_constant<V1 == V2> { using type = T; }; // default_type<T>::value 始终为 true template<typename T> struct default_type : std::true_type { using type = T; }; // 现在我们可以像使用 switch 语句一样使用 disjunction: template<int I> using int_of_size = typename std::disjunction< // values_equal<I, 1, std::int8_t>, // values_equal<I, 2, std::int16_t>, // values_equal<I, 4, std::int32_t>, // values_equal<I, 8, std::int64_t>, // default_type<void> // 必须放在最后! >::type; static_assert(sizeof(int_of_size<1>) == 1); static_assert(sizeof(int_of_size<2>) == 2); static_assert(sizeof(int_of_size<4>) == 4); static_assert(sizeof(int_of_size<8>) == 8); static_assert(std::is_same_v<int_of_size<13>, void>); // 检查 Foo 是否可从 double 构造将导致硬错误 struct Foo { template<class T> struct sfinae_unfriendly_check { static_assert(!std::is_same_v<T, double>); }; template<class T> Foo(T, sfinae_unfriendly_check<T> = {}); }; template<class... Ts> struct first_constructible { template<class T, class...Args> struct is_constructible_x : std::is_constructible<T, Args...> { using type = T; }; struct fallback { static constexpr bool value = true; using type = void; // 未找到匹配类型时的返回类型 }; template<class... Args> using with = typename std::disjunction<is_constructible_x<Ts, Args...>..., fallback>::type; }; // 正常,is_constructible<Foo, double> 未被实例化 static_assert(std::is_same_v<first_constructible<std::string, int, Foo>::with<double>, int>); static_assert(std::is_same_v<first_constructible<std::string, int>::with<>, std::string>); static_assert(std::is_same_v<first_constructible<std::string, int>::with<const char*>, std::string>); static_assert(std::is_same_v<first_constructible<std::string, int>::with<void*>, void>); int main() {}
参见
|
(C++17)
|
逻辑非元函数
(类模板) |
|
(C++17)
|
可变参数逻辑与元函数
(类模板) |