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

rub*_*nvb 23 c++ variadic-templates fold-expression c++17

有没有任何具体的情况下,你不能正确地做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
}
Run Code Online (Sandbox Code Playgroud)

// 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
}
Run Code Online (Sandbox Code Playgroud)

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

Vit*_*meo 27

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

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

template <> 
struct valid_except_void<void> { };
Run Code Online (Sandbox Code Playgroud)

将编译以下内容:

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

constexpr auto inst = test<int, void>;
Run Code Online (Sandbox Code Playgroud)

但是以下内容不会:

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

constexpr auto inst = test<int, void>;
Run Code Online (Sandbox Code Playgroud)

Godbolt.org上的实时示例


来自cppreference

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

  • 小尼特派克:[折叠表达式会造成短路](/sf/ask/3507789211/)。因为它们只需要实例化包中的所有成员,然后再检查值,而`std :: conjunction`仅根据需要实例化成员。仍然+1 (5认同)
  • @ user975989:这不是模板,而是短路::: value`访问。这是通过`conjunction`的实现 (2认同)