JohnYork 2015-06-27 11:48 采纳率: 100%
浏览 5932
已采纳

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 2015-06-28 14: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先生的热心帮助,在他的耐心指导下我终于解决了!

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 如何在3D高斯飞溅的渲染的场景中获得一个可控的旋转物体
  • ¥88 实在没有想法,需要个思路
  • ¥15 MATLAB报错输入参数太多
  • ¥15 python中合并修改日期相同的CSV文件并按照修改日期的名字命名文件
  • ¥15 有赏,i卡绘世画不出
  • ¥15 如何用stata画出文献中常见的安慰剂检验图
  • ¥15 c语言链表结构体数据插入
  • ¥40 使用MATLAB解答线性代数问题
  • ¥15 COCOS的问题COCOS的问题
  • ¥15 FPGA-SRIO初始化失败