考虑一个简单的宏:
#define ECHO(x) x
ECHO(foo(1, 2))
这会产生我们期望的确切输出:
foo(1, 2)
上面的示例有效,因为预处理器可以识别与函数调用相邻的括号。
现在考虑如果我使用模板而不是函数调用会发生什么:
ECHO(template<int, bool>)
这会导致错误,因为预处理器会将template<int
和bool>
解释为宏的两个独立参数。预处理器无法识别<>
范围!
无论如何在宏中使用这样的模板吗?
答案 0 :(得分:11)
#define COMMA ,
ECHO(template<int COMMA bool>)
有点痛苦,但它确实有效。
FWIW,如果参数的语法允许()
s,则不需要替换,例如,
ECHO((a, b))
将适用于单个参数宏,但这并不适用于所有情况(包括您的)。
答案 1 :(得分:5)
可变参数宏可能会有所帮助:
#define ECHO(x...) x
ECHO(foo(1, 2))
ECHO(template<int, bool>)
答案 2 :(得分:1)
如果允许在项目中使用Cog,则代码会变得更具可读性:
/*[[[cog
# definitions ----
import cog
def AddDeclaration( templateArg , restOfDeclaration ):
cog.outl(' %s struct %s; ' % (templateArg , restOfDeclaration))
# generation ---
types = ['bool' , 'std::string']
names = ['Foo' , 'Bar']
for index in range(len(names)):
AddDeclaration( 'template<int, %s>' % types[index] , names[index])
]]]*/
//[[[end]]]
在此文件上运行cog后,您将获得:
/*[[[cog
# definitions ----
import cog
def AddDeclaration( templateArg , restOfDeclaration ):
cog.outl(' %s struct %s; ' % (templateArg , restOfDeclaration))
# generation ---
types = ['bool' , 'std::string']
names = ['Foo' , 'Bar']
for index in range(len(names)):
AddDeclaration( 'template<int, %s>' % types[index] , names[index])
]]]*/
template<int, bool> struct Foo; <---------------- generated by Cog!!
template<int, std::string> struct Bar;
//[[[end]]]
您甚至可以在单独的.py文件中移动您的定义,而cog部分将如下所示:
declarations.py
import cog
def AddDeclaration( templateArg , restOfDeclaration ):
cog.outl(' %s struct %s; ' % (templateArg , restOfDeclaration))
my.h
/*[[[cog
# definitions ----
import declarations
# generation ---
types = ['bool' , 'std::string']
names = ['Foo' , 'Bar']
for index in range(len(names)):
AddDeclaration( 'template<int, %s>' % types[index] , names[index])
]]]*/
template<int, bool> struct Foo;
template<int, std::string> struct Bar;
//[[[end]]]
使用cog的主要优点是您可以完全控制代码生成,完全避免使用boost预处理程序或类似的东西进行不可读的混乱。
主要的缺点是你为项目添加了一个新的工具依赖项,因为你需要使用cog section标记将它的用法包装在注释中,它实际上可能比为小用法手动编写代码更糟糕。当你需要声明大枚举或许多不可避免的样板代码时,它真的得到回报