2 johnyork JohnYork 于 2015.06.27 19:48 提问

C++11中变参数模版和变参数宏混用的问题

定义了一个模版,模版参数定义为可变,想通过宏来实例化,可变的模板参数也通过宏来传递,初步的实现及测试代码如下:

#include <QCoreApplication>
#include <iostream>
// 模板类:
template<typename T, typename... _Args>
struct RuntimeClass
{
   T* (*m_pfnFunction)(_Args&&... __args);
};

// 实例化声明宏:
#define DECL_RUNTIMECLASS(T, className, ...) \
   static RuntimeClass<T, __VA_ARGS__> class_##className;

// 实例化实现宏
#define IMPL_RUNTIMECLASS(T, className, pfnFunc, ...) \
RuntimeClass<T, __VA_ARGS__> className::class_##className\
={pfnFunc};

class TestClass
{
public:
   int TestFunc(void);
    DECL_RUNTIMECLASS(int, TestClass)
};

int TestClass::TestFunc(void)
{
   return 3;
}

IMPL_RUNTIMECLASS(int, TestClass, TestClass::TestFunc)

int main(int argc, char *argv[])
{
   QCoreApplication a(argc, argv);

   TestClass b;
    std::cout<<b.class_TestClass.m_pfnFunction()<<std::endl;

   return a.exec();
}

编译器为MinGW-w64 v4.9.2,编译时报告的错误有:

..\testconsole\main.cpp:12:38: error: template argument 2 is invalid
    static RuntimeClass<T, __VA_ARGS__> class_##className;
                                      ^
..\testconsole\main.cpp:23:5: note: in expansion of macro 'DECL_RUNTIMECLASS'
     DECL_RUNTIMECLASS(int, TestClass)
     ^
..\testconsole\main.cpp:16:28: error: template argument 2 is invalid
 RuntimeClass<T, __VA_ARGS__> className::class_##className\
                            ^
..\testconsole\main.cpp:31:1: note: in expansion of macro 'IMPL_RUNTIMECLASS'
 IMPL_RUNTIMECLASS(int, TestClass, TestClass::TestFunc)
 ^
..\testconsole\main.cpp:17:1: error: invalid type in declaration before '=' token
 ={pfnFunc};
 ^
..\testconsole\main.cpp:31:1: note: in expansion of macro 'IMPL_RUNTIMECLASS'
 IMPL_RUNTIMECLASS(int, TestClass, TestClass::TestFunc)
 ^
..\testconsole\main.cpp:17:10: error: cannot convert 'int (TestClass::*)()' to 'int' in initialization
 ={pfnFunc};
          ^
..\testconsole\main.cpp:31:1: note: in expansion of macro 'IMPL_RUNTIMECLASS'
 IMPL_RUNTIMECLASS(int, TestClass, TestClass::TestFunc)
 ^
..\testconsole\main.cpp: In function 'int main(int, char**)':
..\testconsole\main.cpp:38:34: error: request for member 'm_pfnFunction' in 'TestClass::class_TestClass', which is of non-class type 'int'
     std::cout<<b.class_TestClass.m_pfnFunction()<<std::endl;

初步看起来似乎是变参数宏的__VA_ARGS__用在模板参数上时出的问题,我又尝试了将两个宏的调用代码分别改为:

DECL_RUNTIMECLASS(int, TestClass, void)

IMPL_RUNTIMECLASS(int, TestClass, TestClass::TestFunc, void)

然后编译器报错:

..\testconsole\main.cpp: In instantiation of 'struct RuntimeClass<int, void>':
..\testconsole\main.cpp:31:1:   required from here
..\testconsole\main.cpp:7:41: error: forming reference to void
    T* (*m_pfnFunction)(_Args&&... __args);
                                         ^
..\testconsole\main.cpp:17:10: error: too many initializers for 'RuntimeClass<int, void>'
 ={pfnFunc};
          ^
..\testconsole\main.cpp:31:1: note: in expansion of macro 'IMPL_RUNTIMECLASS'
 IMPL_RUNTIMECLASS(int, TestClass, TestClass::TestFunc, void)
 ^
..\testconsole\main.cpp: In function 'int main(int, char**)':
..\testconsole\main.cpp:38:34: error: 'struct RuntimeClass<int, void>' has no member named 'm_pfnFunction'
     std::cout<<b.class_TestClass.m_pfnFunction()<<std::endl;

目前没什么头绪了,请高手帮忙解决,谢谢!

1个回答

JohnYork
JohnYork   2015.06.28 22:59
已采纳

没人回答吗?
我自己回答吧:
代码中有三处错误:
1. 类TestClass的成员函数TestFunc不是静态成员,不能为struct::m_pfnFunction赋值;
2. struct RuntimeClass::m_pfnFunction的类型是返回值为T*的函数的指针,也与赋值对象TestClass::TestFunc的类型不匹配;
3. 宏DECL_RUNTIMECLASSIMPL_RUNTIMECLASS中的变长宏参数__VA_ARGS__在使用的位置前有逗号时,必须加上前缀##来匹配空的变长宏参数,否则宏展开后将因为存在多余的逗号而导致编译报错。

感谢forum.qt.io用户Chris Kawa先生的热心帮助,在他的耐心指导下我终于解决了!

Csdn user default icon
上传中...
上传图片
插入图片