我正在尝试使用宏来根据类型调用适当的对象。
#define DELEGATE_FUNC(FuncName, kind, paramPtr) \
if (kind == 1) { \
return PolicyObject1.##FuncName(paramPtr); \
} \
else { \
return PolicyObject2.##FuncName(paramPtr); \
} \
return 0; \
(PolicyObject1& PolicyObject2是两个静态对象。) 现在使用宏时,例如
DELEGATE_FUNC(ProcessPreCreate,1,null_ptr);
它在VS 2015中编译得很好,但在LLVM中出现错误"粘贴形成了一个无效的处理令牌' .ProcessPreCreate'"
我找了,发现了一些帖子,并将其理解到某种程度 - 需要双重间接,例如 Why do I need double layer of indirection for macros?
但是我无法定义这两层宏,有人可以帮忙吗?
(请不要讨论设计方面的问题)
由于
答案 0 :(得分:14)
当编译器读取您的C ++文件时,其中一个步骤是将其分为标识符,字符串文字,数字,标点符号等标记.C预处理器可以处理这些标记,而不是文本。 ##
运算符将标记粘合在一起。所以,例如,如果你有
#define triple(foo) foo##3
然后triple(x)
会为您提供标识符x3
,triple(12)
会为您提供整数123
,而triple(.)
会为您提供浮动.3
}}
但是,您所拥有的是.##FuncName
,其中FuncName
是ProcessPreCreate
。这将创建单个标记.ProcessPreCreate
,它不是有效的C ++标记。如果您直接键入PolicyObject1.ProcessPreCreate
而不是宏,则会将其标记为三个令牌:PolicyObject1
,.
和ProcessPreCreate
。这是您的宏需要生成以提供有效的C ++输出。
要做到这一点,只需摆脱##
。没有必要将.
粘贴到FuncName
,因为它们是单独的令牌。要检查这一点,您可以在.
和成员名称之间加一个空格;它仍然可以正常编译。因为它们是独立的代币,所以它们不应该也不能粘在一起。
答案 1 :(得分:0)
删除“ ##”。
#define DELEGATE_FUNC(FuncName, kind, paramPtr) \
if (kind == 1) { \
return PolicyObject1.FuncName(paramPtr); \
} \
else { \
return PolicyObject2.FuncName(paramPtr); \
} \
return 0; \