【问题标题】:C++ preprocessor ## operatorC++ 预处理器## 运算符
【发布时间】:2016-03-01 03:10:34
【问题描述】:

怎么了?我希望 xconcat 线工作。

#define concat(a,b) a ## b
#define xconcat(a,b) concat(a,b)

int main() {
    xconcat(xconcat(boost::variant<,int), >) y;
    boost::variant<int> x;
    return 0;
}

g++ -E x.cpp

# 1 "x.cpp"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "x.cpp"



int main() {
x.cpp:5:1: error: pasting "<" and "int" does not give a valid preprocessing token
x.cpp:5:1: error: pasting "int" and ">" does not give a valid preprocessing token
    boost::variant<int > y;
    boost::variant<int> x;
    return 0;
}

【问题讨论】:

  • 注意:取消标签编辑(删除了 1 个正确的标签,添加了 3 个不正确的标签)

标签: c boost c-preprocessor


【解决方案1】:

从技术上讲,令牌粘贴运算符不能用于粘贴最终不是令牌的内容。 GCC 会强制执行该限制,而其他一些编译器则不会(## 运算符似乎只是执行字符串的基本连接,然后再进行标记化)。

来自 C++11 16.3.3/3 “## 运算符”:

如果结果不是有效的预处理标记,则行为未定义。

几乎所有可追溯到 C90 的 C 和 C++ 标准都采用相同的语言。

在您的情况下,您不需要使用令牌粘贴,因为无论如何您都在处理单独的令牌:

#define yyconcat(a,b) a b
#define yconcat(a,b) yyconcat(a,b)

int main() {
    yconcat(yconcat(boost::variant<,int), >) y;
    boost::variant<int> x;
    return 0;
}

g++ -E so-test.c

C:\so-test>g++ -E so-test.c
# 1 "so-test.c"
# 1 "<command-line>"
# 1 "so-test.c"



int main() {
    boost::variant< int > y;
    boost::variant<int> x;
    return 0;
}

【讨论】:

  • OK “很多”这个词可能太强了。我记得,GCC 是我注意到的唯一一个抱怨这种使用令牌粘贴的编译器。我使用了除 GCC 和 MSVC 之外的一些编译器,但我认为你是对的,它仍然不是“很多”。我认为即使是旧版本的 GCC(如旧版本 v2.95)也没有抱怨,但我可能记错了。
  • #define yconcat(a,b) a b 会更简单
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-06-14
  • 2014-12-04
  • 2023-03-17
  • 1970-01-01
  • 1970-01-01
  • 2018-06-09
  • 1970-01-01
相关资源
最近更新 更多