基于X宏实例化C++模板类报错,求正确实现方法
问题分析与解决方案
错误原因
你的代码使用了运行时if分支判断参数是否为空,但编译器会编译所有分支的代码——哪怕某个分支在运行时不会执行。当处理X(, aaa)时,else分支里的A<a>会被展开为A<>,而模板A要求必须传入1个模板参数,因此触发编译错误。
解决方案
需要让预处理器在参数为空时,完全不生成非法的模板实例化代码,而非依赖运行时分支。以下是两种可行方案:
方案1:宏拼接映射(简洁直观)
利用预处理器的##拼接操作符,为空参数和非空参数分别映射到对应的类:
#include <string.h> #include <iostream> #include <cstdio> #define FOO \ X(, aaa) \ X(int, bbb) \ template <class T> class A { public: A(){ std::cout << "Hello From A\n";} }; class B { public: B() {std::cout << "Hello From B\n";} }; // 定义拼接映射:空参数对应B,int对应A<int> #define A_ B #define A_int A<int> int main() { #define X(a,b) \ do { \ printf("%s is %sempty\n", #b, (0 == strlen(#a)) ? "" : "NOT "); \ A_##a b; // 预处理器拼接:空参数时为A_即B,非空时为A_int即A<int> } while(0) // do-while包裹避免宏展开后的语法冲突 FOO #undef X return 0; }
方案2:预处理器空参数检测(通用扩展性强)
借助宏技巧检测参数是否为空,让预处理器直接跳过非法分支的代码:
#include <string.h> #include <iostream> #include <cstdio> #define FOO \ X(, aaa) \ X(int, bbb) \ template <class T> class A { public: A(){ std::cout << "Hello From A\n";} }; class B { public: B() {std::cout << "Hello From B\n";} }; // 预处理器宏:判断参数是否为空(空返回1,非空返回0) #define IS_EMPTY(...) IS_EMPTY_HELPER(__VA_ARGS__, 0, 1) #define IS_EMPTY_HELPER(_, has_arg, no_arg) no_arg int main() { #define X(a,b) \ if (IS_EMPTY(a)) { \ printf("%s is empty\n", #b); \ B b; \ } else { \ printf("%s is NOT empty\n", #b); \ A<a> b; \ } FOO #undef X return 0; }
内容的提问来源于stack exchange,提问作者Paul Grinberg
相关产品推荐
相关产品推荐

