是否有理由使用std :: conjunction / std :: disjunction而不是在&& // |||上的折叠表达式?

时间:2019-03-14 11:21:58

标签: c++ c++17 variadic-templates fold-expression

在某些特定情况下,您无法正确地使用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
}

vs

// 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
}

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

1 个答案:

答案 0 :(得分:23)

std::conjunction短路了::value实例化,而fold表达式则没有。这意味着,鉴于:

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>;

live example on godbolt.org


来自cppreference

  

连接是短路的:如果存在带有Bi的模板类型参数bool(Bi::value) == false,则实例化conjunction<B1, ..., BN>::value不需要为{{1 }}。