【问题标题】:Boolean concatenation cannot be compiled无法编译布尔连接
【发布时间】:2018-10-13 11:58:37
【问题描述】:

我的 Catch 测试框架中有以下简单的表达式。理想情况下,如果测试失败,测试应该发出警告。

很遗憾,Catch 无法编译以下代码片段:

#define CATCH_CONFIG_MAIN
#include "catch2.hpp"

TEST_CASE("Simple") {
    int a = 4;
    int b = 1;
    CHECK(a == 5 || b == 2);
}

Visual Studio 2015 发出以下错误:

error C2676: Binary operator "||": "const Catch::BinaryExpr<LhsT,const int &>" does not define this operator or a conversion for this operator of to suitable type

我希望得到以下内容:

4==5 || 1==2 => false || false => false

这可以用 Catch 实现还是我必须使用额外的括号:

#define CATCH_CONFIG_MAIN
#include "catch2.hpp"

TEST_CASE("Simple") {
    int a = 4;
    int b = 1;
    CHECK((a == 5 || b == 2));
}

【问题讨论】:

  • 您能告诉我们您遇到了什么错误吗?完整、完整、未经修改并复制粘贴为文本。当然是在问题的正文中,而不是作为评论。
  • 使用额外的括号将无法分解表达式并随意扩展。
  • 另外,你知道右手部分 (b == 2) 甚至不会被评估?

标签: c++ unit-testing catch-unit-test


【解决方案1】:

如果您阅读docs,您会发现一个部分说:

检查(a == 2 || b == 1);这个表达式太复杂了,因为 ||操作员。如果您想检查几个属性之一 持有,您可以将表达式放入括号中(与 && 不同, 表达式分解成几个 CHECK 是不可能的)。

还要注意...

我希望得到以下内容:

4==5 || 1==2 => false || false => false

...您的期望值略有偏差。 || 是短路的,这意味着如果第一个操作数的计算结果为 false,则不计算第二个操作数。

【讨论】:

  • 非常感谢。我应该事先阅读文档。所以我必须依靠括号解决方案。对短路运算符的评论也是完全可以理解的。
  • 顺便说一句,我不相信他们关于 || 的论点“太复杂”,而是宏的限制需要解决方法
  • @Aleph0 即使您得到了解决方案,也请将错误消息添加到您的问题中。它将帮助遇到同样问题的其他人。错误消息通常比“无法编译”更容易搜索和查找;)
  • @user463035818: CATCH 确实 magic 允许通过引入对象来存储操作数和运算符。短路和运算符优先级使 || 对 CATCH 来说太复杂了。
  • @Jarod42 hm 我明白,这只是一个随机的宏咆哮,我自己从未使用过 CATCH。实际上,在阅读了错误消息之后,我不得不承认他们做得很好;)
【解决方案2】:

Catch Classic 用于提供更好的错误,因为它会出错 在实例化一个名为 something 的类型时退出 CATCH_STATIC_ASSERT_EXPRESSION_TOO_COMPLEX_REWRITE_...,但显然 在重写表达式捕获层期间消失了。

无论如何,user463035818已经提供了简单的答案,附上 括号中的表达式。我想扩展为什么表达式包含 不支持运算符&amp;&amp; 或||。

不支持&amp;&amp; 和|| 运算符的原因分为三个部分, 其中两个是实用的,一个是哲学的。

1) 用于分解表达式并漂亮打印它的 TMP 魔法 无法正确模拟内置运算符的短路行为。 这意味着此类表达式的行为将不同于 用户的期望。

2) 已经提到的 TMP 魔法在以下方面相当昂贵 编译时间,即使我们有专门的一元和二进制路径 表达式。有一个可变参数表达式的一般路径可能会 最终变得非常昂贵。

3) 在断言中使用|| 通常是代码(测试)气味。在 一个合理的单元测试,你应该能够表达出预期的结果 确切地说,对于不正确的情况(例如迭代 无序集),合乎逻辑或仍然不是一个好的工具解决方案。

注 1:在单元测试中使用 &amp;&amp;(逻辑与)是完全合理的 事实上,使用&amp;&amp; 重写表达式是相当简单的 编译仍然短路:

REQUIRE((expr1 && expr2 && expr3));

REQUIRE(expr1);
REQUIRE(expr2);
REQUIRE(expr3);

注 2:这开始是对另一个答案的评论,但后来它 超过了允许的长度,我注意到错误消息 Catch2 确实不好,所以我opened up an issue。

【讨论】:

  • 很好的解释。我同意测试|| 是一种测试气味。另一方面,有时A || B 是您需要测试的确切条件
猜你喜欢
  • 2012-03-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-04
  • 1970-01-01
  • 2013-11-08
相关资源
最近更新 更多