c++ - Macro concatenation using compiler define -
this should simple, i'm struggling figure out. have project_name compiler (g++) -d define, , want concatenate other text form namespace name. current approach this:
#define version_namespace project_name ## versioning for current project, expect version_namespace syren_dllversioning. instead compiler error:
error: 'project_nameversioning' has not been declared but according g++ call, project_name being defined properly:
ccache g++ ... -dproject_name=syren_dll ... why project_name not being replaced before concatenation takes place?
a macro name not expanded when appears next ## operator, need more layers of indirection:
#define p_version2(foo) foo ## versioning #define p_version(foo) p_version2(foo) #define version_namespace p_version(project_name) so project_name expanded argument of p_version , concatenated in p_version2.
in section 16.3.3 [cpp.concat], paragraph 3, specified
for both object-like , function-like macro invocations, before replacement list reexamined more macro names replace, each instance of
##preprocessing token in replacement list (not argument) deleted , preceding preprocessing token concatenated following preprocessing token.
that preprocessing tokens adjacent ## preprocessing token concatenated before macro-replacement done on replacement list. therefore, project_name must passed through (function-like) macro replaced , concatenated versioning.
but in 16.3.1 [cpp.subst], paragraph 1, standard specifies (emphasis added me)
after arguments invocation of function-like macro have been identified, argument substitution takes place. parameter in replacement list, unless preceded
#or##preprocessing token or followed##preprocessing token (see below), replaced corresponding argument after macros contained therein have been expanded. before being substituted, each argument’s preprocessing tokens macro replaced if formed rest of preprocessing file; no other preprocessing tokens available.
that macro parameters not subject further macro-expansion if adjacent ## preprocessing token. therefore, function-like macro receives project_name argument must not directly concatenate argument versioning, expand project_name must call function-like macro concatenation.
so in above, invocation ccache g++ ... -dproject_name=syren_dll ..., project_name replaced syren_dll when p_version(project_name) expanded, resulting in p_version2(syren_dll) leads concatenation of syren_dll , versioning.
Comments
Post a Comment