22 c++ parameters macros templates
我正在尝试编译下面的一段代码,我在专门用于std :: vector的行上得到一个错误,似乎传入的一个参数在某种程度上被假定为两个参数.它可能与角括号有关吗?
是否有一种特殊的方式/机制,通过这些参数可以正确地传递给宏?
#include <vector>
template<typename A>
struct AClass {};
#define specialize_AClass(X)\
template<> struct AClass<X> { X a; };
specialize_AClass(int) //ok
specialize_AClass(std::vector<int,std::allocator<int> >) //error
int main()
{
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我得到的错误如下:
1 Line 55: error: macro "specialize_AClass" passed 2 arguments, but takes just 1
2 Line 15: error: expected constructor, destructor, or type conversion before 'int'
3 compilation terminated due to -Wfatal-errors.
Run Code Online (Sandbox Code Playgroud)
Joh*_*itb 10
你有两个选择.其中一个已经提到:使用__VA_ARGS__.然而,它的缺点是它不能在严格的C++ 03中工作,但需要足够的C99/C++ 0x兼容预处理器.
另一个选项是括起类型名称.但与另一个答案声称不同,它并不像仅仅使用类型名称括起来那么容易.如下编写专业化是不正确的
// error, NOT valid!
template<> struct AClass<(int)> { X a; };
Run Code Online (Sandbox Code Playgroud)
通过在括号中传递类型名称,然后构建一个函数类型,我已经解决了这个问题(并且可能会在引擎盖下使用它)
template<typename T> struct get_first_param;
template<typename R, typename P1> struct get_first_param<R(P1)> {
typedef P1 type;
};
Run Code Online (Sandbox Code Playgroud)
用它get_first_param<void(X)>::type表示类型X.现在您可以将宏重写为
#define specialize_AClass(X) \
template<> struct AClass<get_first_param<void X>::type> {
get_first_param<void X>::type a;
};
Run Code Online (Sandbox Code Playgroud)
而你只需要传递包含在括号中的类型.
小智 10
template<typename TypeX, typename TypeY>
class Test
{
public:
void fun(TypeX x, TypeY y)
{
std::wcout << _T("Hello") << std::endl;
std::wcout << x << std::endl;
std::wcout << y << std::endl;
}
};
#define COMMOA ,
#define KK(x) x val;
void main()
{
KK(Test<int COMMOA int>);
val.fun(12, 13);
}
Run Code Online (Sandbox Code Playgroud)
我有一种解决这个问题的新方法.希望它可以帮到你:)
这里有几个问题.
首先,宏非常愚蠢,它们很复杂,但基本上相当于一个纯文本替换过程.
因此,您公开的代码存在2个(技术)问题:
BOOST_FOREACH是一个众所周知的库,但他们唯一可以做的就是告诉用户它的参数不应该包含逗号,除非它们可以包含在括号,但并非总是如此>>在模板特化的末尾创建一个符号,这将无法正确解析.有预处理/模板元编程技巧,但更简单的解决方案是使用没有逗号的类型:
typedef std::vector<int, std::allocator<int> > FooVector;
specialize_AClass(FooVector)
Run Code Online (Sandbox Code Playgroud)
最后,存在一个美学问题,因为它们的普遍性,宏最好给出不可能与"常规"(类型,函数,变量)名称冲突的名称.共识通常是使用所有大写标识符,如:
SPECIALIZE_ACLASS
Run Code Online (Sandbox Code Playgroud)
请注意,这不能以下划线开头,因为标准限制使用标识符匹配_[A-Z].*或[^_]*__.*标准库的编译器编写者或他们想要的任何东西(那些不是表情符号:p)
由于预处理器在语义分析之前运行,因此模板参数中的逗号将被解释为宏的参数分隔符。相反,您应该能够使用可变参数宏来执行以下操作:
#define specialize_AClass(...)\
template<> struct AClass< __VA_ARGS__ > { X a; };
Run Code Online (Sandbox Code Playgroud)