首页 > 解决方案 > 是否有理由使用 std::conjunction/std::disjunction 而不是“&&”/“||”上的折叠表达式?

问题描述

是否有任何特定情况您不能正确使用std::conjunction/std::disjunction并且不使用更“基本”(即语言功能而不是库功能)折叠表达&&/ ||

例子:

// func is enabled if all Ts... have the same type
template<typename T, typename... Ts>
std::enable_if_t<std::conjunction_v<std::is_same<T, Ts>...> >
func(T, Ts...) {
 // TODO something to show
}

对比

// func is enabled if all Ts... have the same type
template<typename T, typename... Ts>
std::enable_if_t<(std::is_same<T, Ts> &&...)>
func(T, Ts...) {
 // TODO something to show
}

使用折叠表达式的版本更简短,通常更易读(尽管对此可能有不同的看法)。所以我不明白为什么将它与折叠表达式一起添加到库中。

标签: c++c++17variadic-templatesfold-expression

解决方案


std::conjunction短路::value实例化,而折叠表达式没有。这意味着,给定:

template <typename T> 
struct valid_except_void : std::false_type { };

template <> 
struct valid_except_void<void> { };

以下将编译:

template <typename... Ts>
constexpr auto test = std::conjunction_v<valid_except_void<Ts>...>;

constexpr auto inst = test<int, void>;

但以下不会:

template <typename... Ts>
constexpr auto test = (valid_except_void<Ts>::value && ...);

constexpr auto inst = test<int, void>;

godbolt.org 上的实时示例


cppreference

连词是短路:如果有一个模板类型参数Bibool(Bi::value) == false那么实例化conjunction<B1, ..., BN>::value不需要实例化Bj::valuefor j > i


推荐阅读