【问题标题】:Cascaded macros in gcc C++14 vs msvc++ 2015gcc C++ 14 与 msvc++ 2015 中的级联宏
【发布时间】:2016-07-21 20:34:40
【问题描述】:

我有以下代码在 msvc 2015 下工作:

#define CLASS_JS_PSG_PROPERTY_EX(PROPERTY, VALUE) \
static bool Get##PROPERTY(/*irrelevant params here...*/) \
{ \
...
 some particular code
...
    return true; \
}

#define CLASS_JS_PSG_PROPERTY(VALUE) \
CLASS_JS_PSG_PROPERTY_EX(##VALUE, VALUE)

...

#define kProp 1

CLASS_JS_PSG_PROPERTY_EX(Version, kProp)

CLASS_JS_PSG_PROPERTY(kProp)

这应该定义名为 GetVersionGetkProp 的方法。

现在,这在 gcc C++14(实际上是 TDM-GCC-64)下会出现以下错误:

pasting "(" and "kProp" does not give a valid preprocessing token

应该如何编写才能在gcc C++14msvc 2015下编译?

【问题讨论】:

  • 试试CLASS_JS_PSG_PROPERTY_EX(VALUE, VALUE)
  • 在这种情况下,它会尝试生成名称为 Get"Version"Get"kProp" 的函数。
  • 这应该只发生在#VALUE,而不是VALUE
  • 我的错,我想说 Version 或 kProp 的内容在那里。容器宏会将参数替换为它们的内容并将它们传递给内部宏(如果它们是字符串,则作为字符串,如果它们是具有 1 作为值的 int,则作为“1”)。
  • #define kProp 1。它已经过预处理,因此不会使用名称kProp,而是使用值1

标签: c++ gcc visual-c++


【解决方案1】:

诀窍是 - 如果您不想将名称扩展为宏,则必须立即将其传递给 ## 运算符 - 但连接的结果必须是有效的标记。像这样的:

#include <iostream>

#define CLASS_JS_PSG_PROPERTY_EX_HELPER(GetName) \
static bool GetName() { return true; }


#define CLASS_JS_PSG_PROPERTY_EX(PROPERTY, VALUE) \
CLASS_JS_PSG_PROPERTY_EX_HELPER(Get##PROPERTY)

#define CLASS_JS_PSG_PROPERTY(VALUE) \
CLASS_JS_PSG_PROPERTY_EX_HELPER(Get##VALUE)


#define kProp 1

CLASS_JS_PSG_PROPERTY_EX(Version, kProp)

CLASS_JS_PSG_PROPERTY(kProp)

int main() {
    std::cout << GetVersion() + GetkProp();
}

适用于 gccMSVC

您的原始代码似乎与 MSVC 一起工作的原因是因为 MSVC 预处理器是出了名的不合格 - 它对字符流(错误)而不是令牌流(正确)进行操作。在CLASS_JS_PSG_PROPERTY_EX(##VALUE, VALUE) 中,## 不是您所建议的一元运算符 - 它是将(VALUE 粘合到单个标记(VALUE 中的二元运算符。这不是一个有效的预处理令牌,所以程序格式错误,这就是 GCC 抱怨的地方。但是 MSVC 预处理器后来将这个无意义的标记分解成碎片(符合标准的预处理器永远不会这样做)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-03-25
    • 2020-08-13
    • 2016-03-10
    • 2021-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多