-4

file Base.h

class Base {
}

file A.h

class A : public Base {
}

file B.h

class B : public Base {
}

file C.h

#define D_CLASS A

file C.cpp

#include "c.h"
#include D_CLASS##.h          // <--- how to make the header from class name?

Base * pBase = new D_CLASS() ;

The incentive in doing this...
System that support different operating systems, each OS has header file that tell the builder the name of class to create in order to provide certain functionality.
when user adds it's new OS he needs also to define his specific class name with that functionality.

teach me
  • 453
  • 5
  • 20

1 Answers1

0

You can do it this way:

#define PP_ADD_HDR_SUFFIX(x) PP_ADD_HDR_SUFFIX_IMPL(x)
#define PP_ADD_HDR_SUFFIX_IMPL(x) x.h

#define PP_QUOTE(x) PP_QUOTE_IMPL(x)
#define PP_QUOTE_IMPL(x) # x

#define CLASS_HEADER_NAME(name) PP_QUOTE(PP_ADD_HDR_SUFFIX(name))

#include "C.h"
#include CLASS_HEADER_NAME(D_CLASS)

Base * pBase = new D_CLASS();

It basically expands to this:

#include #D_CLASS.h

The (second) '#' is to create a string literal (quotes around the file name) and there is actually no need for token pasting, just the macro expansion.

However as others mentioned, you should better have a good use case for this.

I did that in the past when I wanted to support "configurable" header files (configurable preposition/namespace of the classes). And as far as I can remember, at the end it was looking quite messy :).


Similarly, if you'd like to "pre-process" system headers (like #include <my_name.h>), you can do:

#define CLASS_NAME my_name

#define CLASS_SYSTEM_HEADER_NAME(name) CLASS_SYSTEM_HEADER_NAME_IMPL(name)
#define CLASS_SYSTEM_HEADER_NAME_IMPL(name) <name.h>

#include CLASS_HEADER_NAME(CLASS_NAME)
EmDroid
  • 5,918
  • 18
  • 18
  • Did you actually *try* this? It doesn't work (except possibly on non-standard preprocessors like MSVC): [Live on coliru](http://coliru.stacked-crooked.com/a/970792cf9a7e6aa1): "error: pasting "ctype" and "." does not give a valid preprocessing token" – rici Jan 03 '17 at 16:16
  • I tried it in MSVC where it works. But will try in different compilers (maybe I did it slightly different in the past because I know that it was working in most compilers, I'll try to look it up). – EmDroid Jan 03 '17 at 16:41
  • Updated with the version working in at least MSVC and GCC (which I tested). In the fact it's actually even simpler, no need for token pasting at all :) (also tested that it works with the coliru example) – EmDroid Jan 03 '17 at 17:06
  • yes, the point is that token pasting is not only unnecessary but illegal; the file path is not (usually) a valid *token*. – rici Jan 03 '17 at 18:20
  • the first one doesn't work with clang, the second one works great for system headers, I need it as: #include "my_header.h" – teach me Jan 03 '17 at 20:45
  • Strange, for me the first works also with clang (3.4-1ubuntu3) ... what is the error message you are getting? – EmDroid Jan 04 '17 at 09:29