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

问题描述 投票:5回答:2

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

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

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

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

谢谢

c++ macros llvm llvm-clang
2个回答
14
投票

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

#define triple(foo) foo##3

然后triple(x)将获得标识符x3triple(12)将获得整数123triple(.)将获得浮动.3

然而,你所拥有的是.##FuncName,其中FuncNameProcessPreCreate。这将创建单个标记.ProcessPreCreate,它不是有效的C ++标记。如果您直接键入PolicyObject1.ProcessPreCreate而不是通过宏,它将被标记为三个标记:PolicyObject1.ProcessPreCreate。这是您的宏需要生成以提供有效的C ++输出。

要做到这一点,只需摆脱##。没有必要将.粘贴到FuncName上,因为它们是单独的令牌。要检查这一点,你可以在.和成员名称之间加一个空格;它仍然可以正常编译。由于它们是独立的令牌,因此它们不应该也不能粘在一起。


0
投票

删除“##”。

#define DELEGATE_FUNC(FuncName, kind, paramPtr)         \
if (kind == 1) {                                    \
    return PolicyObject1.FuncName(paramPtr);      \
}                                                   \
else {                                              \
    return PolicyObject2.FuncName(paramPtr);      \
}                                                   \
return 0;                                           \
© www.soinside.com 2019 - 2024. All rights reserved.