首先是模板实例化与宏扩展
What comes first - template instantiation vs. macro expansion?
让我们考虑一个这样的代码示例(它只是一个将define
和template
结合起来的人为示例,不要寻找任何意义):
#define COMMA ,
template <typename A> class Test
{
public:
Test(){}
void Foo(A var COMMA int test);
};
Test<int> Knarz;
问题:
我的假设是否正确,首先预处理器将搜索/替换所有出现的逗号,其次编译器将按该顺序实例化任何模板?
随访:
如果上面的答案是"是",正如我希望的那样,你能解释为什么这个使用模板和定义的解决方案有效吗?
处理器在编译本身完成之前运行,因此您假设预处理器将在模板实例化之前替换COMMA
是正确的。
对于您的后续工作:该解决方案与模板关系不大。问题是预处理器会将大括号内的逗号作为宏的参数分隔符,因为它不会解析C++代码以查看它是模板参数的分隔符。因此,COMMA
宏用于仅在替换MOCK_CONSTANT_METHOD0
后插入用于分隔模板参数的,
。然而,我不确定这是否保证有效,因为我不知道记忆宏替换顺序的保证。如果在MOCK_CONSTANT_METHOD0
之前替换COMMA
,一切都会分崩离析,代码再次无法编译。
编辑:在研究了标准之后,我认为解决方案通常应该有效,因为预处理器会首先找到MOCK_CONSTANT_METHOD0
并替换它。只有这样,它才会检查替换的结果以查找COMMA
宏。虽然不能保证。
首先是宏和模板,实际上是宏在编译之前只对现有代码应用更改。因此,在此解决方案中,逗号将生成一个模板代码,如下所示:
MOCK_CONSTANT_METHOD0(aMethod, const QMap<QString,QString>());
在编译之前。
所以对于第二个问题:
它与 gmock 框架的工作方式有关,实际上MOCK_CONSTANT_METHOD0是一个宏,因此该行将被转换为其他内容。Markus Mayr 说逗号将被翻译为参数分隔符,因此它与在这种情况下如何转换 gmock 宏有关,我想首先将替换模拟宏,然后逗号将在内部应用,这就是为什么它确实适用于宏而不仅仅是逗号的原因。
预处理器是第一个。
我认为引用的解决方案是一个非常糟糕的主意,因为它取决于预处理器执行其替换的顺序。由于整个字符仅用于防止预处理器在模板参数列表中的逗号上阻塞,因此最好使用 typedef。
翻译有 9 个阶段。
我的假设是否正确,首先预处理器将 搜索/替换所有出现的
COMMA
,其次编译器将 按该顺序实例化任何模板?
COMMA
令牌在第 4 阶段被替换。
模板在第 8 阶段实例化。
- 从C++实例化QML
- 设计一个只能由特定类实例化的类(如果可能的话,通过make_unique)
- 如何创建一个空的全局类并在启动时实例化它
- 在两个类中共享相同的函数调用,并在不需要时避免空实例化
- 约束和显式模板实例化
- 为什么包含windows.h会产生语法错误,从而阻止类的实例化?(C2146,C2065)
- 对象实例化调用构造函数的次数太多
- 如何使用非默认构造函数实例化模板化类
- 静态数据成员模板专用化的实例化点在哪里
- 错误的cv::face FacemarkLBF实例化
- C++的解析器在可以区分比较和模板实例化之前会做什么?
- 为什么 gcc 和 clang 为函数模板的实例化生成不同的符号名称?
- 检查某些类型是否是模板类 std::optional 的实例化
- 我有一个对象,它将在整个程序的持续时间内实例化,但一个类成员不会,我应该动态分配它吗?
- [temp.variadic]中关于包扩展实例化的措辞
- 如何在代码中创建抽象类,让蓝图扩展它,并将该蓝图返回给代码进行实例化?
- 扩展模板化类以在对象实例上具有运算符 bool<bool>
- 如何在PHP扩展中实例化全局C++类
- 首先是模板实例化与宏扩展
- 扩展类和实例化