【问题标题】:Folding expressions in C++17 - Usecase for comparison operatorsC++17 中的折叠表达式 - 比较运算符的用例
【发布时间】:2016-05-21 09:44:57
【问题描述】:

根据N4295 C++17 将允许我计算未知数量的参数的总和:

template<typename ... T>
int sum(T...t)
{
    return (... + t);
}

该文档进一步指出,我可以使用 == 或 > 等运算符来代替 +。任何人都可以想出一个明智的例子来说明我什么时候想在这样的结构中使用 == 或 >?

(我意识到人们可以定义 == 和 > 来对奇怪的类做奇怪的事情,但这肯定违反了良好的做法。写 a &gt; b &gt; c &gt; d 几乎不是一个好主意,不是吗?)

【问题讨论】:

  • 如果你使用带有一些特殊起始元素的二元折叠,也许你可以说(apply_op() == ... == t)apply_opoperator== 做正确的事?
  • 据我记得,一元折叠被删除了 +。您必须写 (T{} + ... + t)(t + ... + T{})(或任何对您有意义的值)。
  • @chris 只有在参数包为空时才被移除。只要...t 中至少有一个元素,上述函数仍然可以按预期工作。
  • @Morwenn,很有趣,我从来没听过那部分。
  • @chris 好吧,我们的目标是防止在没有给定参数时使用默认的int-typed 0,这可能会导致在这种特定情况下调用不正确的重载。提供参数后,返回类型取决于参数的类型,这通常是预期的行为。只有空箱子很棘手。

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


【解决方案1】:

如果链式比较像在 Python 中那样处理,其中 a &lt; b &lt; c 被解释为 a &lt; b and b &lt; c 并且单个评估为 b,我将是一个有趣的功能。不幸的是,在 C++ 中情况并非如此,即使在奇怪的情况下,折叠比较运算符确实没有意义。

请注意,a proposal (P0313) 实际上从折叠表达式处理的运算符中完全删除运算符 ==!=&lt;&gt;&lt;=&gt;=。 2016 年 6 月在奥卢召开的委员会会议上对此进行了讨论。删除的动机相当简短:

比较运算符在折叠表达式中没有多大意义;它们扩展到具有惊人效果的表达式,因此仅对 dsl 元程序员有用。 [...] 能够修复像 a &lt; b &lt; c 这样的表达式会很好。那将需要一台时间机器。不重复折叠表达式的问题似乎是可行的。

也就是说提案被拒绝了。

【讨论】:

  • 可以重载这样的操作符以不同的方式表现,折叠会产生一些不错的特性。也许;)
  • 我喜欢“混合折叠”,你可以说“t op1 ... op2”用于一元折叠,“t op1 ... op2 e”用于扩展为“t1 op1”的二进制折叠t2 op2 t2 op1 t3 ..."。
  • @JohannesSchaub-litb 是时候写另一个提案了吗? :p
  • @JohannesSchaub-litb 或者更确切地说,有一个采用t...op 的语法,并产生一个包t1 op t2 ...(每个相邻对)。然后将标准折叠应用于 that 会给你你想要的。现在,如果我们可以让操作员返回包,这可以定义为 (except_last(t) op1 except_first(t)) op2 ... 或类似的。
【解决方案2】:

这不是“单独的 == 直接折叠”,而是“&& 与涉及 == 的表达式折叠。然而,这是我用来比较值的解决方案,也许这也是您想到的那种应用程序。

这对我来说适用于 g++ 和 clang++

template <typename TYPE, typename... TYPE_TAIL>
constexpr bool same_value([[maybe_unused]] TYPE value, TYPE_TAIL... value_tail)
{
  return (... && (value == value_tail));
}

static_assert(same_value(3));
static_assert(same_value(3, 3));
static_assert(!same_value(3, 1));
static_assert(same_value(3, 3, 3));
static_assert(!same_value(3, 1, 3));

int main() {}

编译:

clang++ -std=c++1z testFold.cpp -o testFold

(版本:clang 5.0.0-+rc2-1 (tags/RELEASE_500/rc2))

g++ -std=c++17 testFold.cpp -o testFold

(版本:g++(Debian 7.2.0-8)7.2.0)

[[maybe_unused]] 可防止编译器在仅使用一个参数调用 same_value(one_arg) 时向您发出警告,因为在这种情况下,函数会返回 && 运算符的中性值(即 true)。

【讨论】:

    【解决方案3】:

    在用例上是expression templates,比较运算符(例如operator ==)返回一个类对象而不是bool

    不过,即使在这里,我也很难想出一个有用的例子。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-21
      • 2020-01-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多