问题
I am having trouble with the preprocessor token pasting operator in gcc 4.7.1 (std=c++11). Namely, consider the following code:
// 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)
Usage scenarios - first the map definitions:
std::map<std::string,std::string> GLOBAL_MAP(my_map);
namespace SomeNamespace
{
std::map<std::string,std::string> GLOBAL_MAP(my_map);
}
Now the usage:
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
}
What I believe might be happening is that it is interpreting GLOBAL_MAP
after ##
as a token for pasting rather than a macro to be further expanded. How do I get around this?
回答1:
Token pasting generates a single token for the compiler to read. This isn’t what you want here — ::
is a valid C++ token on its own, but ::g_map_my_map
isn’t a token that the compiler knows.
Hence, remove the token pasting operator:
#define NS_QUAL_GLOBAL_MAP(type) SomeNamespace::GLOBAL_MAP(type)
回答2:
You don't need the ##
operator after ::
. The ##
operator is used to form a single token, but SomeNamespace::g_map_mymap
are multiple tokens anyway. Just do
#define NS_QUAL_GLOBAL_MAP(type) SomeNamespace::GLOBAL_MAP(type)
回答3:
You just want SomeNamespace:: GLOBAL_MAP(name)
.
You can't join a name like g_map_my_map
to the ::
token, because ::g_map_my_map
is not a valid token, it's two tokens. So just put them next to each other, don't try to join them.
来源:https://stackoverflow.com/questions/32252643/c-preprocessor-token-pasting-for-namespace-qualification