首先是什么 - 模板实例化与宏扩展?

时间:2012-04-18 11:17:44

标签: c++ templates macros c-preprocessor

让我们考虑一下像这样的代码示例(它只是一个人为的例子,可以将definetemplate结合起来,不要有任何意义吗?:

#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有效?

4 个答案:

答案 0 :(得分:10)

预编译器在编译本身完成之前运行,因此您假设预处理器将在模板实例化之前替换COMMA是正确的。

您的后续跟进: 该解决方案与模板几乎没有关系。问题在于预处理器会将大括号内的逗号作为宏的参数分隔符,因为它不会解析C ++代码以查看它是模板参数的分隔符。因此COMMA宏仅用于在,被替换后插入MOCK_CONSTANT_METHOD0来分隔模板参数。然而,我不确定这是否有效,因为我不知道内存宏替换顺序的保证。如果COMMAMOCK_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)

9 phases of translation

  

我的假设是否正确,首先是预处理器   搜索/替换所有出现的COMMA,其次是编译器   按顺序实例化任何模板?

在阶段4中替换COMMA标记。
模板在第8阶段实例化。