views:

1211

answers:

3

Hi,

Initially I thought I needed this, but I eventually avoided it. However, my curiosity (and appetite for knowledge, hum) make me ask:

Can a preprocessor macro, for instance in

#include "MyClass.h"

INSTANTIATE_FOO_TEMPLATE_CLASS(MyClass)

expand to another include, like in

#include "MyClass.h"

#include "FooTemplate.h"
template class FooTemplate<MyClass>;

? Thanks!

+8  A: 

I believe that cannot be done, this is because the pre-processor is single pass. So it cannot emit other preprocessor directives.

Specifically, from the C99 Standard (6.10.3.4 paragraph 3):

3 The resulting completely macro-replaced preprocessing token sequence is not processed as a preprocessing directive even if it resembles one, ...

Interestingly enough, This is why the unary _Pragma operator was added to c99. Because #pragma could not be emited by macros, but _Pragma can.

Evan Teran
Well, it can of course emit the directives. what it cannot do is process them in the same preprocessor pass.
anon
Since the `#` and `##` characters have special meanings in macros, I don't see how you could actually emit a directive...
Evan Teran
Actually the GCC preprocessor seems to allow "#define X #ifdef X" where the space between the #ifdef and the second X is really a newline, and this actually emits a #ifdef when you run cpp on it. Someone else might like to check this, as I've just had a couple of beers :-)
anon
Yea, it seems that it is possible to create something that "resembles" a directive, but the standard specifically states (see my edit) that such a construct is not processed as a directive.
Evan Teran
Yes, I wasn't suggesting that the OP could do what he appears to want.
anon
+5  A: 

The C standard says this about preprocessing directives (C99 - 6.10(2) - Preprocessing directives):

A preprocessing directive consists of a sequence of preprocessing tokens that begins with a # preprocessing token that (at the start of translation phase 4) ...

and (C99 - 6.10(7)):

The preprocessing tokens within a preprocessing directive are not subject to macro expansion unless otherwise stated.

EXAMPLE In:

#define EMPTY
EMPTY # include <file.h>

the sequence of preprocessing tokens on the second line is not a preprocessing directive, because it does not begin with a # at the start of translation phase 4, even though it will do so after the macro EMPTY has been replaced

So, no, macros cannot expand into a '#include' preprocessing directive. Those directives need to be in place at the start of translation phase 4 (when handling those directives takes place preprocessing happens). Since macro expansion occurs during phase 4, macros can't cause something to exist at the start of phase 4.

I'd like to point out however, that the following does work:

#ifdef WIN32
#define PLATFORM_HEADER "platform/windows/platform.h"
#else
#define PLATFORM_HEADER "platform/linux/platform.h"

#include PLATFORM_HEADER

because the C standard says this (C99, 6.10.2(4) - Source file inclusion):

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.)

Michael Burr
i looked at that part of the standard, but I don't think it is the most relevant section. The example is not one that tries to emit a directive. It is instead an example of a directive which is not preceeded by "whitespace" (even though the EMPTY macro resolves to whitespace).
Evan Teran
I'd agree that your quote from the standard is more directly relevant, but it wan't there when I answered. Even if the example above isn't the same as what's asked about, the bit about the preprocessing directive needing to be in place at the start of phase 4 also disallows macros from explanding into useful preprocessing directives, even if 6.10.3.4(3) says so more directly. (in other words, even if I don't think my answer is incorrect, yours is clearly a better answer).
Michael Burr
Fair enough, you make a good point, +1 :-).
Evan Teran
Sorry, but I had to choose a good answer. Another +1 on your insightful comment to be as fair as possible, I hope you understand.
moala
No need to apologize - Evan's answer is definitely better. There's no need to apologize even if that weren't the case.
Michael Burr
+1  A: 

All preprocessor directives are interpreted before macro expansion begins, so no, you cannot have a macro expand into an #include directive and have it be interpreted as such. Instead, it will be interpreted as (erroneous) C++ code.

John Bode
You might get this impression because many directives disable macro expansion of their arguments, but this is not true. Macro expansion happens concurrently with directive parsing. If it were true, #if would not work, and #undef would not have the effect people expect.
Zack