C++ CPPUNIT_ASSERT 有两个参数

C++ CPPUNIT_ASSERT with two parameters

在一些代码中我发现了以下行:

CPPUNIT_ASSERT(1, val.getBytefield().size());

这真的比较两个参数是否相等吗?通常,我希望与 CPPUNIT_ASSERT_EQUAL:

进行比较
CPPUNIT_ASSERT_EQUAL(1, val.getBytefield().size());

测试编译并且断言在情况 1 中有效,但在情况 2 中不行。区别在哪里?

对我来说,这看起来像是损坏的代码,可能是进行了一些重构或其他编辑的结果。

CPPUNIT_ASSERT 宏接受一个参数——一个条件表达式——并断言该条件为真(,如果为假则失败)。

这段代码试图传递两个参数,但这里的逗号不是用作参数分隔符,而是实际上用作(有点晦涩)comma operator。逗号运算符计算其第一个操作数,丢弃结果,然后计算第二个操作数的结果。因此,最初的 1 是一个无关紧要的空操作。代码相当于:

CPPUNIT_ASSERT(val.getBytefield().size());

这意味着它断言字节字段的大小不为零。

显然,这与您的第二段代码不同:

CPPUNIT_ASSERT_EQUAL(1, val.getBytefield().size());

断言字节字段的大小正好等于 1。

看来您使用的编译器有一个扩展,它接受单个参数宏的 2 个参数。我猜是 MSVC,参见 this

因此,宏将检查第一个参数是否为真,在您的情况下,它是 1,它根据上下文转换为 booltrue,由 this expansion

#define CPPUNIT_ASSERT(C) \
( CPPUNIT_NS::Asserter::failIf( !(C),                                   \
                                 CPPUNIT_NS::Message( "assertion failed",         \
                                                      "Expression: " #C), \
                                 CPPUNIT_SOURCELINE() ) )

您可以通过更改来仔细检查我的声明:

CPPUNIT_ASSERT(1, val.getBytefield().size());

与:

CPPUNIT_ASSERT(1000, val.getBytefield().size());

CPPUNIT_ASSERT_EQUAL(1, val.getBytefield().size());

根据我的实验,.size() 很可能 return 一个 std::size_t。来自 definition of CPPUNIT_ASSERT_EQUAL:

#define CPPUNIT_ASSERT_EQUAL(expected,actual) \
                (assertEquals((expected),          \
                          (actual),                \
                          CPPUNIT_SOURCELINE(),    \
                          "" ) )

assertEquals

template<class T>
void assertEquals   (   const T &   expected,
    const T &   actual,
    SourceLine  sourceLine,
    const std::string &     message
)   

因为1(int)的类型和.size()(std::size_t)的return类型不同,所以找不到匹配的函数, 编译器无法编译你的代码。


我认为这是解决方案:

CPPUNIT_ASSERT(1 == val.getBytefield().size());
CPPUNIT_ASSERT_EQUAL(std::size_t(1), val.getBytefield().size());