【问题标题】:C++ preprocessor token pasting for namespace qualification命名空间限定的 C++ 预处理器标记粘贴
【发布时间】:2015-11-22 00:41:27
【问题描述】:

我在使用 gcc 4.7.1 (std=c++11) 中的预处理器标记粘贴运算符时遇到问题。即,考虑以下代码:

// Create a name for a global map (this works)
#define GLOBAL_MAP(name) g_map_ ## name // This works fine

// Now, namespace qualify this map (this fails to compile when used)
#define NS_QUAL_GLOBAL_MAP(name) SomeNamespace:: ## GLOBAL_MAP(name)

使用场景——首先是地图定义:

std::map<std::string,std::string> GLOBAL_MAP(my_map);

namespace SomeNamespace
{

std::map<std::string,std::string> GLOBAL_MAP(my_map);

}

现在的用法:

void foo()
{
    bar(GLOBAL_MAP(my_map)); // This compiles fine
    baz(NS_QUAL_GLOBAL_MAP(my_map)); // This fails to compile with:
                                     // error: pasting "::" and "NAME_MAP" does not give a
                                     // valid preprocessing token
}

我认为可能发生的情况是,它将## 之后的GLOBAL_MAP 解释为用于粘贴的标记,而不是要进一步扩展的宏。我该如何解决这个问题?

【问题讨论】:

  • 为什么有人会否决一个完全合法的 C++ 预处理器问题/错误?有些人的傲慢让我震惊。
  • 我认为它没有显示任何研究成果并且没有用处。错误给出了答案:pasting "::" and "NAME_MAP" does not give a valid preprocessing token"。阅读错误似乎是面对编译器错误时应该进行的最低限度的研究。
  • @Jonathan,我阅读了错误并理解了错误。我只是不确定为什么会出现错误。当这被接受的答案解释时,很明显我添加了一种预处理器“间接级别”,在某种意义上说,这是没有必要的。对这类问题投反对票除了傲慢之外别无他法。当我们在这里编程和查询它们时,我们都会犯错误,即使它们是暂时的头脑放屁的结果,这也是 StackOverflow 的全部意义所在。
  • 而且我不认为暂时的头脑放屁会产生一个对未来有帮助的好问题。你问了这个问题,得到了答案,太好了。但我不认为解决临时的头脑放屁对网站的长期有用。当问题是由一个简单的拼写错误造成的,这是一个有效的关闭原因,我认为一个容易纠正的简单错误几乎属于同一类别。 (更不用说您没有按照“为什么此代码不起作用?”问题的要求发布 MCVE,这是关闭和/或否决投票的另一个原因)。跨度>
  • 作为记录,注意到@JonathanWakely 的 cmets,我认为这个问题在 3 年后非常有用。真正的问题是“解决方法是什么?”答案很好地提供了这一点。并非每个问题都需要惊天动地才有用。

标签: c++ c++11 c-preprocessor


【解决方案1】:

标记粘贴会生成一个单个标记供编译器读取。这不是您想要的——:: 本身就是一个有效的 C++ 标记,但 ::g_map_my_map 不是编译器知道的标记。

因此,移除标记粘贴操作符:

#define NS_QUAL_GLOBAL_MAP(type) SomeNamespace::GLOBAL_MAP(type)

【讨论】:

  • 废话!我在想什么:)? +1!为你推迟复选标记,为我提供更多咖啡......
【解决方案2】:

:: 之后不需要## 运算符。 ## 运算符用于形成一个单个 标记,但SomeNamespace::g_map_mymap 无论如何都是多个标记。做吧

#define NS_QUAL_GLOBAL_MAP(type) SomeNamespace::GLOBAL_MAP(type)

【讨论】:

    【解决方案3】:

    你只想要SomeNamespace:: GLOBAL_MAP(name)

    您不能将g_map_my_map 之类的名称加入:: 令牌,因为::g_map_my_map 不是有效令牌,它是两个令牌。所以只要把它们放在一起,不要试图加入它们。

    【讨论】:

      猜你喜欢
      • 2013-01-25
      • 1970-01-01
      • 2014-06-14
      • 1970-01-01
      • 2021-09-20
      • 2020-03-18
      • 2011-04-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多