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,它根据上下文转换为 bool
值 true
,由 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(), \
"" ) )
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());
在一些代码中我发现了以下行:
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,它根据上下文转换为 bool
值 true
,由 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(), \
"" ) )
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());