为什么这个宏接受带有 1 个参数的模板而拒绝带有 2 个参数的模板?

Why this macro accepts a template with 1 parameter and refuses a template with 2 parameters?

我正在使用 CPPUNIT 1.12.1。

它定义了那些宏:

#define CPPUNIT_TEST_SUITE_ADD_TEST( test ) \
      context.addTest( test )

#define CPPUNIT_TEST( testMethod )                        \
    CPPUNIT_TEST_SUITE_ADD_TEST(                           \
        ( new CPPUNIT_NS::TestCaller<TestFixtureType>(    \
                  context.getTestNameFor( #testMethod),   \
                  &TestFixtureType::testMethod,           \
                  context.makeFixture() ) ) )

我想使用模板将许多测试添加到同一个测试套件(因为 CPPUNIT 工作,每个测试都必须是一个 void 函数,所以使用模板可以调用相同的 void功能不同 "parameters"...).

这非常有效:

class MyTestSuite1 : public CPPUNIT_NS::TestFixture
{
    CPPUNIT_TEST_SUITE(MyTestSuite1);
    CPPUNIT_TEST(doTest<false>);
    CPPUNIT_TEST(doTest<true>);
    CPPUNIT_TEST_SUITE_END();

    template<bool param> void doTest() { /* test here */ }
};
CPPUNIT_TEST_SUITE_REGISTRATION(MyTestSuite1);

虽然这不是:

class MyTestSuite2 : public CPPUNIT_NS::TestFixture
{
    CPPUNIT_TEST_SUITE(MyTestSuite2);
    CPPUNIT_TEST(doTest<false,false>);
    CPPUNIT_TEST(doTest<true,false>);
    CPPUNIT_TEST_SUITE_END();

    template<bool param1,bool param2> void doTest() { /* test here */ }
};
CPPUNIT_TEST_SUITE_REGISTRATION(MyTestSuite2);

编译器(Visual Studio 2015)报告:

1>b:\dev\vobs_diabeloop\private\tst\regulation\cppunit\hyper_ftac3\test.cpp(20): warning C4002: too many actual parameters for macro 'CPPUNIT_TEST' 1>b:\dev\vobs_diabeloop\private\tst\regulation\cppunit\hyper_ftac3\test.cpp(21): warning C4002: too many actual parameters for macro 'CPPUNIT_TEST' 1>b:\dev\vobs_diabeloop\private\tst\regulation\cppunit\hyper_ftac3\test.cpp(20): error C2059: syntax error: ')' 1>b:\dev\vobs_diabeloop\private\tst\regulation\cppunit\hyper_ftac3\test.cpp(21): error C2059: syntax error: ')' 1>b:\dev\vobs_diabeloop\private\tst\regulation\cppunit\hyper_ftac3\test.cpp(22): error C2143: syntax error: missing ';' before '}' 1>b:\dev\vobs_diabeloop\private\tst\regulation\cppunit\hyper_ftac3\test.cpp(22): error C2065: 'namer': undeclared identifier 1>b:\dev\vobs_diabeloop\private\tst\regulation\cppunit\hyper_ftac3\test.cpp(22): error C2065: 'factory': undeclared identifier 1>b:\dev\vobs_diabeloop\private\tst\regulation\cppunit\hyper_ftac3\test.cpp(22): error C2059: syntax error: ')' 1>b:\dev\vobs_diabeloop\private\tst\regulation\cppunit\hyper_ftac3\test.cpp(29): error C2143: syntax error: missing ';' before '{' 1>b:\dev\vobs_diabeloop\private\tst\regulation\cppunit\hyper_ftac3\test.cpp(30): error C2143: syntax error: missing ';' before '{'

这是为什么?宏如何正确处理 1 个模板参数,但处理两个模板参数却失败?知道如何轻松编译和工作吗?

编辑: 已经尝试 CPPUNIT_TEST((doTest<false,false>)); 没有成功(得到 error C2143: syntax error: missing ';' before ')'

这个有用吗?

CPPUNIT_TEST((doTest<false,false>));
CPPUNIT_TEST((doTest<true,false>));

有时宏在解析逗号时会很棘手...

, 在 MACRO 中被解析为分隔符(被父包围时除外)。

解决方法

使用中间宏:

#define COMMA ,

CPPUNIT_TEST(doTest<false COMMA false>);

或修复您原来的 MACRO 以处理逗号:

#define CPPUNIT_TEST(testMethod, ...)                           \
    CPPUNIT_TEST_SUITE_ADD_TEST(                                \
        ( new CPPUNIT_NS::TestCaller<TestFixtureType>(          \
                  context.getTestNameFor( #testMethod),         \
                  &TestFixtureType::testMethod , ##__VA_ARGS__, \
                  context.makeFixture() ) ) )
CPPUNIT_TEST(doTest<false,false>);

这个不起作用,因为宏认为您传递了 2 个宏参数:doTest<falsefalse>


CPPUNIT_TEST((doTest<false,false>));

这不起作用,因为 &TestFixtureType::testMethod 将扩展为无效的 &TestFixtureType::(doTest<false,false>)


正如 Piotr 在评论中提到的,您可以使用此代码:

#define COMMA ,
class MyTestSuite2 : public CPPUNIT_NS::TestFixture
{
    CPPUNIT_TEST_SUITE(MyTestSuite2);
    CPPUNIT_TEST(doTest<false COMMA false>);
    CPPUNIT_TEST(doTest<true COMMA  false>);
    CPPUNIT_TEST_SUITE_END();

    template<bool param1, bool param2> void doTest() { /* test here */ }
};
CPPUNIT_TEST_SUITE_REGISTRATION(MyTestSuite2);

因为预处理器看到你想传递 1 个参数