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

流过昼夜 提交于 2019-12-12 04:12:34

问题


I'm working with CPPUNIT 1.12.1.

It has those macro defined:

#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() ) ) )

I want to add many tests to the same test suite using templates (as CPPUNIT works, every test must be a void function, so using template makes it possible to call the same void function with different "parameters"...).

This works perfectly:

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);

while this does not:

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);

Compiler (Visual Studio 2015) reports:

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 '{'

Why is that? How could the macro handle correctly 1 template parameter, but fails for two? Any idea how I could easily have it compile and work?

Edit: Already tried CPPUNIT_TEST((doTest<false,false>)); without success (getting error C2143: syntax error: missing ';' before ')')


回答1:


CPPUNIT_TEST(doTest<false,false>);

This one doesn't work because macro thinks you are passing 2 macro parameters: doTest<false and false>.


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

This doesn't work because &TestFixtureType::testMethod will expand to &TestFixtureType::(doTest<false,false>) which is invalid.


As mentioned by Piotr in comment, you can use this code:

#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);

Because pre-processor sees that you want to pass 1 parameter




回答2:


, is parsed as separator in MACRO (except when surrounded by parent).

way of work-around

using intermediate MACRO:

#define COMMA ,

CPPUNIT_TEST(doTest<false COMMA false>);

Or fix your original MACRO to handle comma:

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



回答3:


does this work?

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

sometimes Macros can be tricky when parsing commas...



来源:https://stackoverflow.com/questions/41565773/why-this-macro-accepts-a-template-with-1-parameter-and-refuses-a-template-with-2

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!