Being faced with the question whether it's possible to choose #include
s in the preprocessor I immediately thought not possible.
.. Only to later find out that it is indeed possible and you only need to watch out for argument expansions (which e.g. Boost.Preprocessor can take care of).
While I'd avoid actually doing that for includes if possible, I'd like to know why this works. At the moment I fail to get a useful understanding in the C++ or C standard.
Are parameterized macros allowed for any preprocessor-directive? (except #define
/#undef
)
Can someone reference where this is allowed and summarize it?
Example for the curious utilizing Boost.Preprocessor for simplicity:
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/stringize.hpp>
#define INC_LOCAL(a,b) BOOST_PP_STRINGIZE(BOOST_PP_CAT(BOOST_PP_CAT(a,b),.h))
#define INC_GLOBAL(a,b) BOOST_PP_CAT(BOOST_PP_CAT(<,a),BOOST_PP_CAT(b,>))
#include INC_LOCAL(loc,al) // #include "local.h"
#include INC_GLOBAL(vect,or) // #include <vector>
Update: Referenced C standard, clarified question.
From § 16.2-4 ("Source file inclusion") of C++ 2003 draft:
§ 6.10.2-4 of C99 says the same.
The "two previous forms" mentioned above are
# include <h-char-sequence>
and# include "q-char-sequence"
. The section seems too simple to summarize.For other directives, macro expansion isn't performed on any
identifier
preprocessing token (note this behavior is not defined by the grammar, but by C++ § 16 / C § 6.10):#line
is explicitly macro-expanded by C++ § 16.4-5 / C § 6.10.4-5. Expansion for#error
(C++ § 16.5 / C § 6.10.5) and#pragma
(C++ § 16.6 / C § 6.10.6) isn't mentioned. C++ § 16.3-7 / C 6.10.3-8 states:C++ § 16.3.1 / C § 6.10.3.1-1 tells us that when the arguments to a macro function are substituted into the
replacement-list
, they are first macro expanded. Similarly, C++ § 16.3.4 / C § 6.10.3.4 has the preprocessor macro-expand thereplacement-list
after substitution.In summary, macro expansion is done for
#if
,#elif
,#include
,#line
, the arguments to a macro function and the body of a macro function when substituted. I think that's everything.It's a very fundamental feature of the C preprocessor -- for example, a directive such as
#ifdef
makes zero sense except when used with an argument that's possibly a macro (if you had to know that the argument is not allowed to be a macro, what could the purpose of#ifdef
possibly be?!).I'm not sure how chapter and verse of the ISO C standard would help you -- the C++ standard, as I recall, does not change the preprocessor's operation anyway.