让我们考虑一下像这样的代码示例(它只是一个人为的例子,可以将define
和template
结合起来,不要有任何意义吗?:
#define COMMA ,
template <typename A> class Test
{
public:
Test(){}
void Foo(A var COMMA int test);
};
Test<int> Knarz;
问题:
我的假设是否正确,首先预处理器将搜索/替换所有出现的COMMA和 second ,编译器将按该顺序实例化任何模板?
跟进:
如果上述答案为“是”,我希望能解释为什么这个solution using templates and defines有效?
答案 0 :(得分:10)
预编译器在编译本身完成之前运行,因此您假设预处理器将在模板实例化之前替换COMMA
是正确的。
您的后续跟进:
该解决方案与模板几乎没有关系。问题在于预处理器会将大括号内的逗号作为宏的参数分隔符,因为它不会解析C ++代码以查看它是模板参数的分隔符。因此COMMA
宏仅用于在,
被替换后插入MOCK_CONSTANT_METHOD0
来分隔模板参数。然而,我不确定这是否有效,因为我不知道内存宏替换顺序的保证。如果COMMA
在MOCK_CONSTANT_METHOD0
之前被替换,那么一切都会崩溃,而且代码再次无法编译。
编辑:在查看标准后,我认为解决方案通常应该有效,因为预处理器将首先找到MOCK_CONSTANT_METHOD0
并替换它。只有这样,它才会检查替换的结果以找到COMMA
宏。但不保证。
答案 1 :(得分:3)
之后的第一个宏和模板,实际上宏只会在编译之前对现有代码应用更改。因此,在此解决方案中,逗号将生成模板代码,如:
MOCK_CONSTANT_METHOD0(aMethod, const QMap<QString,QString>());
编译之前。
所以对于第二个问题:
它与gmock框架的工作方式有关,实际上MOCK_CONSTANT_METHOD0是一个宏,因此该行将转换为其他内容。 Markus Mayr说逗号将被翻译为参数分隔符,因此它与gmock宏在这种情况下的转换方式有关我想首先将替换模拟宏,并且在内部应用逗号之后这就是它之所以能用于宏,而不仅仅是逗号。
答案 2 :(得分:1)
预处理器是第一个。
我认为引用的解决方案是一个非常糟糕的主意,因为它取决于预处理器执行替换的顺序。由于整个charade仅用于防止预处理器阻塞模板参数列表中的逗号,因此使用typedef要好得多。
答案 3 :(得分:0)
我的假设是否正确,首先是预处理器 搜索/替换所有出现的
COMMA
,其次是编译器 按顺序实例化任何模板?
在阶段4中替换COMMA
标记。
模板在第8阶段实例化。