【问题标题】:Is there a reason to use std::conjunction/std::disjunction instead of a fold expression over "&&"/"||"?是否有理由使用 std::conjunction/std::disjunction 而不是“&&”/“||”上的折叠表达式?
【发布时间】:2019-03-14 11:21:57
【问题描述】:

是否存在您无法正确使用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
}

使用折叠表达式的版本更简洁,通常更具可读性(尽管意见可能不同)。所以我不明白为什么将它与折叠表达式一起添加到库中。

【问题讨论】:

  • conjunctiondisjunction 的“内部”实现在 C++17 折叠表达式不可用(无论出于何种原因)的项目中仍然有用。

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


【解决方案1】:

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

live example on godbolt.org


来自cppreference

连接是短路的:如果有一个模板类型参数Bibool(Bi::value) == false,那么实例化conjunction&lt;B1, ..., BN&gt;::value 不需要实例化Bj::valuej &gt; i

【讨论】:

  • 小吹牛:Fold expressions do short circuit。他们只需要在检查值之前实例化包的所有成员,而std::conjunction 只根据需要实例化成员。还是 +1
  • 是什么导致模板无法实例化?那个函数是特殊的还是所有不直接使用的参数包都保持未实例化?
  • @user975989:不是模板,而是::value 访问被短路。这是通过conjunction的实现来完成的
  • conjunction/disjunction总是定义了::value的标准类型特征一起使用有什么意义吗?还是我对这个假设有误?
  • @r3musn0x 避免不必要的实例化
猜你喜欢
  • 2021-12-01
  • 2020-10-31
  • 2016-07-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-23
  • 2021-05-22
  • 2010-12-29
相关资源
最近更新 更多