用于命名空间限定的c++预处理器令牌粘贴

C++ preprocessor token pasting for namespace qualification

本文关键字:处理器 令牌 预处理 c++ 命名空间 用于      更新时间:2023-10-16

我在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++令牌,但::g_map_my_map不是编译器知道的令牌。

因此,删除令牌粘贴操作符:

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

::之后不需要##操作符。##运算符用于形成单个令牌,但SomeNamespace::g_map_mymap无论如何都是多个令牌。只做

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

你只需要SomeNamespace:: GLOBAL_MAP(name)

您不能将g_map_my_map这样的名称加入::令牌,因为::g_map_my_map不是一个有效的令牌,它是两个令牌。所以把它们放在一起就行了,不要把它们连在一起