10

让我们考虑一个这样的代码示例(它只是一个人为的例子来结合defineand template,不要寻找任何意义它):

#define COMMA ,

template <typename A> class Test
{
public:
    Test(){}

    void Foo(A var COMMA int test);
};

Test<int> Knarz;

问题:

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

跟进:

如果上面的答案是“”,正如我所希望的那样,你能解释为什么这个使用模板和定义的解决方案有效吗?

4

4 回答 4

13

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

供您跟进:该解决方案与模板几乎没有关系。问题在于预处理器将大括号内的逗号作为宏的参数分隔符,因为它不会解析 C++ 代码以查看它是模板参数的分隔符。因此,宏仅在替换后才COMMA用于插入,分隔模板参数。MOCK_CONSTANT_METHOD0但是我不确定这是否可以保证工作,因为我不知道内存宏替换顺序的保证。IfCOMMA将在MOCK_CONSTANT_METHOD0一切崩溃并且代码再次无法编译之前被替换。

编辑:查看标准后,我认为该解决方案通常应该有效,因为预处理器会MOCK_CONSTANT_METHOD0首先找到并替换它。只有这样,它才会检查替换的结果以找到COMMA宏。虽然没有保证。

于 2012-04-18T11:21:02.567 回答
3

首先是宏和模板,实际上宏只会在编译之前将更改应用于现有代码。所以在这个解决方案中,逗号将生成一个模板代码,如:

MOCK_CONSTANT_METHOD0(aMethod, const QMap<QString,QString>());

在编译之前。

所以对于第二个问题:

它与 gmock 框架的实际工作方式有关, MOCK_CONSTANT_METHOD0 是一个宏,因此该行将转换为其他内容。Markus Mayr 说逗号将被翻译为参数分隔符,因此它与在这种情况下如何转换 gmock 宏有关,我猜首先将替换模拟宏,然后在内部应用逗号,这就是为什么它可以使用宏而不仅仅是逗号。

于 2012-04-18T11:20:49.760 回答
1

预处理器是第一个。

我认为引用的解决方案是一个非常糟糕的主意,因为它取决于预处理器执行替换的顺序。由于整个字符集仅用于防止预处理器卡住模板参数列表中的逗号,因此使用 typedef 会好得多。

于 2012-04-18T11:21:37.980 回答
0

翻译有9个阶段

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

在第COMMA4 阶段替换令牌
。在第 8 阶段实例化模板。

于 2016-06-25T18:55:06.033 回答