English 中文(简体)
Macros as arguments to preprocessor directives
原标题:

Being faced with the question whether it s possible to choose #includes 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:

A preprocessing directive of the form

# include pp-tokens new-line 

(that does not match one of the two previous forms) is permitted. The preprocessing tokens after include in the directive are processed just as in normal text (each identifier currently defined as a macro name is replaced by its replacement list of preprocessing tokens).

§ 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):

# if constant-expression new-line [group] 
# ifdef identifier new-line [group] 
# ifndef identifier new-line [group] 
# elif constant-expression new-line [group] 
# else new-line [group] 
# endif new-line 
# include pp-tokens new-line 
# define identifier replacement-list new-line 
# define identifier lparen [identifier-list] ) replacement-list new-line 
# undef identifier new-line 
# line pp-tokens new-line 
# error [pp-tokens] new-line 
# pragma [pp-tokens] new-line 
# new-line 

#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:

If a # preprocessing token, followed by an identifier, occurs lexically at the point at which a preprocessing directive could begin, the identifier is not subject to macro replacement.

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 the replacement-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.





相关问题
Undefined reference

I m getting this linker error. I know a way around it, but it s bugging me because another part of the project s linking fine and it s designed almost identically. First, I have namespace LCD. Then I ...

C++ Equivalent of Tidy

Is there an equivalent to tidy for HTML code for C++? I have searched on the internet, but I find nothing but C++ wrappers for tidy, etc... I think the keyword tidy is what has me hung up. I am ...

Template Classes in C++ ... a required skill set?

I m new to C++ and am wondering how much time I should invest in learning how to implement template classes. Are they widely used in industry, or is this something I should move through quickly?

Print possible strings created from a Number

Given a 10 digit Telephone Number, we have to print all possible strings created from that. The mapping of the numbers is the one as exactly on a phone s keypad. i.e. for 1,0-> No Letter for 2->...

typedef ing STL wstring

Why is it when i do the following i get errors when relating to with wchar_t? namespace Foo { typedef std::wstring String; } Now i declare all my strings as Foo::String through out the program, ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

Window iconification status via Xlib

Is it possible to check with the means of pure X11/Xlib only whether the given window is iconified/minimized, and, if it is, how?

热门标签