粘贴形成了无效的处理令牌'。

时间:2017-09-22 03:03:52

标签: c++ macros llvm llvm-clang

我正在尝试使用宏来根据类型调用适当的对象。

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

但是我无法定义这两层宏,有人可以帮忙吗?

(请不要讨论设计方面的问题)

由于

2 个答案:

答案 0 :(得分:14)

当编译器读取您的C ++文件时,其中一个步骤是将其分为标识符,字符串文字,数字,标点符号等标记.C预处理器可以处理这些标记,而不是文本##运算符将标记粘合在一起。所以,例如,如果你有

#define triple(foo) foo##3

然后triple(x)会为您提供标识符x3triple(12)会为您提供整数123,而triple(.)会为您提供浮动.3 }}

但是,您所拥有的是.##FuncName,其中FuncNameProcessPreCreate。这将创建单个标记.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;                                           \