std::conjunction和std::disjunction是C++17引入的编译期逻辑“与”“或”工具,接受类型参数(如std::true_type或类型特征),支持短路求值;配合std::negation可简洁表达复杂约束,提升SFINAE和concept-like条件的可读性与实用性。

std::conjunction 和 std::disjunction 是 C++17 引入的模板元编程工具,用于在编译期对多个类型特征(如 std::is_integral_v<T>)或布尔常量进行逻辑“与”和逻辑“或”运算。
它们本质是编译期布尔值的折叠
这两个类模板不是函数,而是可变参数模板别名,内部利用模板偏特化实现短路语义(类似运行时 && / || 的行为):
-
std::conjunction<B1, B2, ..., BN>:当所有模板参数
Bi都是std::true_type(即其::value为true)时,整个表达式为true;任意一个为false,立即得false(不实例化后续)。 -
std::disjunction<B1, B2, ..., BN>:只要有一个
Bi是std::true_type,结果就是true;全为false才得false;遇到第一个true就停止(短路)。
使用场景:简化 SFINAE 和约束条件
以前写多个 std::enable_if_t 嵌套很麻烦,现在可以直接组合判断:
- 比如要求类型
T同时是整型、有默认构造、且可复制:
template<typename T>
std::enable_if_t<std::conjunction_v<
std::is_integral_v<T>,
std::is_default_constructible_v<T>,
std::is_copy_constructible_v<T>
>> foo() { /* ... */ }- 又如:允许传入任意一个支持
size()或length()成员的类型:
template<typename T>
std::enable_if_t<std::disjunction_v<
std::is_member_function_pointer_v<decltype(&T::size)>,
std::is_member_function_pointer_v<decltype(&T::length)>
>> bar(const T& t) { /* ... */ }注意:参数必须是类型,不是布尔值字面量
你不能直接写 std::conjunction<true, false> —— 这会编译失败。必须传入满足 std::bool_constant<...> 接口的类型,比如:
立即学习“C++免费学习笔记(深入)”;
- ✅ 正确:
std::conjunction<std::true_type, std::is_same<int, int>> - ✅ 更常用(C++17 起推荐):
std::conjunction_v<std::is_integral<int>, std::is_signed<int>>(_v后缀是value的变量模板) - ❌ 错误:
std::conjunction<true, std::is_integral<int>>(true不是类型)
还有 std::negation:逻辑非
虽然没在标题里提,但它常和前两者搭配使用:
-
std::negation<std::is_void<T>>::value等价于!std::is_void_v<T> -
std::negation_v<std::is_reference<T>>更简洁
它也支持短路(单参数,意义不大),但语义清晰、可读性好。
基本上就这些。它们不复杂,但让模板约束更接近自然语言逻辑,避免深层嵌套和手写特化,是现代 C++ 元编程的实用基础工具。








