Namespaces
Variants

std:: conjunction

From cppreference.net
Metaprogramming library
Type traits
Type categories
(C++11)
(C++11) ( DR* )
Type properties
(C++11)
(C++11)
(C++14)
(C++11) (deprecated in C++26)
(C++11) ( until C++20* )
(C++11) (deprecated in C++20)
(C++11)
Type trait constants
Metafunctions
conjunction
(C++17)
(C++17)
Supported operations
Relationships and property queries
Type modifications
Type transformations
(C++11) (deprecated in C++23)
(C++11) (deprecated in C++23)
(C++11)
(C++11) ( until C++20* ) (C++17)

Compile-time rational arithmetic
Compile-time integer sequences
定义于头文件 <type_traits>
template < class ... B >
struct conjunction ;
(C++17 起)

形成类型特征 B... 逻辑合取 ,实质上对特征序列执行逻辑与运算。

特化 std :: conjunction < B1, ..., BN > 具有一个公开且无歧义的基类,该基类是

  • sizeof... ( B ) == 0 ,则为 std:: true_type ;否则
  • 返回 B1, ..., BN 中首个满足 bool ( Bi :: value ) == false 的类型 Bi ,若不存在此类类型则返回 BN

基类成员名称(除 conjunction operator= 外)不会被隐藏,且在 conjunction 中可无歧义地访问。

合取操作具有短路特性:如果存在模板类型参数 Bi 满足 bool ( Bi :: value ) == false ,则实例化 conjunction < B1, ..., BN > :: value 时不需要对 j > i Bj :: value 进行实例化。

如果程序为 std::conjunction std::conjunction_v 添加特化,则行为未定义。

目录

模板参数

B... - 每个实例化的模板参数 Bi 必须满足:能作为基类使用,且定义的成员 value 可转换为 bool 类型

辅助变量模板

template < class ... B >
constexpr bool conjunction_v = conjunction < B... > :: value ;
(C++17 起)

可能的实现

template<class...>
struct conjunction : std::true_type {};
template<class B1>
struct conjunction<B1> : B1 {};
template<class B1, class... Bn>
struct conjunction<B1, Bn...>
    : std::conditional_t<bool(B1::value), conjunction<Bn...>, B1> {};

注释

conjunction 的特化不一定继承自 std:: true_type std:: false_type :它仅继承自第一个其 ::value (显式转换为 bool 后)为 false B ,或在所有 B 均转换为 true 时继承自最后一个 B 。例如, std :: conjunction < std:: integral_constant < int , 2 > , std:: integral_constant < int , 4 >> :: value 的值为 4

短路实例化机制使 conjunction 区别于 折叠表达式 :折叠表达式(例如 ( ... && Bs :: value ) 会实例化 Bs 中的每个 B ,而 std :: conjunction_v < Bs... > 会在值可确定时立即停止实例化。当后续类型实例化成本高昂或使用错误类型实例化会导致硬错误时,这一特性尤为实用。

功能测试 标准 功能
__cpp_lib_logical_traits 201510L (C++17) 逻辑运算符类型特征

示例

#include <iostream>
#include <type_traits>
// 当所有 Ts... 的类型都与 T 相同时启用 func
template<typename T, typename... Ts>
std::enable_if_t<std::conjunction_v<std::is_same<T, Ts>...>>
func(T, Ts...)
{
    std::cout << "All types in pack are the same.\n";
}
// 否则
template<typename T, typename... Ts>
std::enable_if_t<!std::conjunction_v<std::is_same<T, Ts>...>>
func(T, Ts...)
{
    std::cout << "Not all types in pack are the same.\n";
}
template<typename T, typename... Ts>
constexpr bool all_types_are_same = std::conjunction_v<std::is_same<T, Ts>...>;
static_assert(all_types_are_same<int, int, int>);
static_assert(not all_types_are_same<int, int&, int>);
int main()
{
    func(1, 2, 3);
    func(1, 2, "hello!");
}

输出:

All types in pack are the same.
Not all types in pack are the same.

参见

(C++17)
逻辑非元函数
(类模板)
变参逻辑或元函数
(类模板)