C/C++ #define Macro inside macro?

15,212

Solution 1

What's the problem with

#ifdef __cplusplus
#define C_OR_CPP(C, CPP) CPP
#else
#define C_OR_CPP(C, CPP) C
#endif

(Leaving names with double underscore to the implementation per phresnel remark)

Solution 2

My English is poor, and I'm sorry for language mistakes and typos if any.

If #ifdef must not wrap the macro invocation, there is a solution not so graceful.

g++ only: You may try this in selective occasions. But if there are commas in a or b, workarounds are still needed. It's simply based on the fact that __cplusplus is defined to "1" when in a C++ environment and remains itself while not.

#define SELECT1(a, b) a
#define SELECT__cplusplus(a, b) b
#define xcat(a,b)  a##b
#define concat(...) xcat(__VA_ARGS__)
#define C_OR_CPP(C, CPP) concat(SELECT, __cplusplus)(C, CPP)

C_OR_CPP(1, 2)

Other Environments Check the __cplusplus macro, a compiler that comforming to standard C++ should generate

 #define __cplusplus value 

and value should >= 199711L

Solution 3

Not in C++. But you can

#ifdef __cplusplus
# define CPP
#else
# define C
#endif

I assume this is just a pathological example by you. Note also that double underscore is reserved to library implementors (see 17.6.4.3.2 Global names).

vector, but in C i want it to simply be void, you know.

So, what speaks against a solution like

struct Foo {
  #ifdef __cplusplus
  ...
  #else
  ...
  #endif
};

or what speaks against providing different APIs for different programming languages?

Solution 4

AProgrammer already given you the right answer, but the answer to the "is it possible" part of the question is no. Macro expansion doesn't occur until after all preprocessor directives have been handled, so any macro that expands into a #define or #ifdef will be passed to the compiler as regular source text, which will cause the compiler to yak.

Share:
15,212
imacake
Author by

imacake

Im a linux fanboy. (and Rainbow Dash)

Updated on June 25, 2022

Comments

  • imacake
    imacake almost 2 years

    I would like something like:

    #define C_OR_CPP(C__, CPP__) #ifdef __cplusplus\
    CPP__\
    #else\
    C__\
    #endif
    

    Is it possible? Maybe some dirty hack with #include ?

    Reason: I make a header where a struct uses a member variable of type vector<stuff>*, but in C i want it to simply be void*, you know.

    TIA

  • imacake
    imacake about 12 years
    You mean like, CPP in your example would be vector<stuff>* and C would be void* ? That is good, havent thought of it. Will consider it in case no other solution is found.
  • Mike DeSimone
    Mike DeSimone about 12 years
    This is how it's done in every case I've seen. For example, this pattern is used to define a macro for WEAK (meaning that a given function definition can be replaced by another with the same name in another compilation unit, rather than stopping the linker with a multiple-definition error) depending on the compiler in use (e.g. gcc or IAR or Keil).
  • imacake
    imacake about 12 years
    Different APIs: NO. I am actually working on a program with the believ everything in world derives from one rule, and should simplify towards it(have that philosophy for years in my head, now writing a program to suit it). (the solution example): That looks very unclean and is harder to read. Why not ask about something better? =D
  • Sebastian Mach
    Sebastian Mach about 12 years
    @imacake: I am confused about the rule thing, what has this to do with C vs. C++?
  • imacake
    imacake about 12 years
    The header will be used by both, C and C++ programs. There is obviously no vector<T>* in C. The C or C++ programs would give it to be managed by a special managing part which resides in a shared library. github.com/linuxrocksrulers/m6 There yet isnt much code, but follow it in case you want loadable classes at runtime
  • Ian Kenney
    Ian Kenney about 11 years
    Not sure what this adds to the accepted answer by @AProgrammer