views:

100

answers:

3

On a cross-platform project, I want to #include a header file whose name contains the name of the platform. I have a #define macro for the platform.

So for example, for

#define PLATFORM win32

I want

#include "engine\win32\devices_win32.h"

while for

#define PLATFORM linux

I want

#include "engine\linux\devices_linux.h"


I'm going with Richard Pennington's answer, minus one line of code - it works for me!

#define PLATFORM Linux
#define xstr(x) #x
#define str(x) xstr(x)
#define sub(x) x
#include str(sub(engine/PLATFORM/devices_)PLATFORM.h)

Thanks everyone!

+8  A: 

Usually, you would do something more like:

#ifdef WIN32
#include "devices_win32.h"
#endif
#ifdef LINUX
#include "devices_linux.h"
#endif

...rather than having a single PLATFORM definition which can be set differently depending on the platform.

Charles Salvia
This way is much better than the computed include, because it is standardly used and every reader of the code immediatelly knows what is happening.
danatel
+4  A: 
#define PLATFORM Linux
#define xstr(x) #x
#define str(x) xstr(x)
#define sub(x) x
#define FILE str(sub(engine/PLATFORM/devices_)PLATFORM.h)

#include FILE

I'm not sure I'd use it, though. ;-) I had to use Linux rather than linux because linux is defined as 1 in my compiler.

Richard Pennington
I tried this on gcc, and it actually works. I'm surprised, because the C++ standard seems to say this shouldn't work. 16.3.7 reads `"If a # preprocessing token, followed by an identifier, occurs lexically at the point in which a preprocessing directive could begin, the identifier is not subject to macro replacement."` The way I read that, an #include directive would not be subject to macro replacement. But apparently it works, so either I'm misunderstanding what the standard says, or gcc is violating the standard. (Most likely the former.)
Charles Salvia
Charles, it works with my preprocessor also, which is based on the one used by clang. I think it is standard C.
Richard Pennington
The rule you quote forbids changing #define foo include ... #foo.
Richard Pennington
@Charles:The relevant part of the standard for this is §16.2/4.
Jerry Coffin
@Jerry, you're right. Well, I'm upvoting this because it does exactly what the OP wants, even though it's ugly.
Charles Salvia
works without the #define FILE... step which is exactly what I want - thanks!
Tim Gradwell
A: 

Well in practice, this could be achieved using something like

#define PLATFORM win32

#define INCLUDE_FILE devices_ ## PLATFORM

#define QUOTED_INCLUDE_FILE #INCLUDE_FILE

#include QUOTED_INCLUDE_FILE

but the the following rule would prevent you from doing this:

C comments and predefined macro names are not recognized inside a #include' directive in which the file name is delimited with <' and `>'.

C comments and predefined macro names are never recognized within a character or string constant. (Strictly speaking, this is the rule, not an exception, but it is worth noting here anyway.)

Aurélien Vallée
Do you have a source for the rule you quoted? It doesn't seem to match the rules in the C++ (or C) standard.
Jerry Coffin
This is a quote from the GCC documentation available at:http://gcc.gnu.org/onlinedocs/gcc-2.95.3/cpp_1.html. Chapter 1 "The C Proprocessor" section 1 "Transformations Made Globally"
Aurélien Vallée