为什么这个宏接受带有 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<false
和 false>
。
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 个参数
我正在使用 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<false
和 false>
。
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 个参数