1

wrt: C preprocessor macro specialisation based on an argument

I am trying to use this technique to compare to 'void', however it also matches 'void *'.

Has anybody else seen this problem ? Is there a known solution ?

The source contains thousands of lines with preprocessor macros, so it is not easily readable. However it is like this:

#define GIVE_A_FUNCTION(RetType,Name,ArgType1)\
RetType Name(ArgType1 ArgName1) \
{ \
SWITCH_ON_VOID( \
   RetType,\
   ,\
   RetType value =)\
GetValue(); \
PostProcessing(); \
SWITCH_ON_VOID( \
   RetType,\
   ,\
   return value;)\
}

This expands to nothing if type is 'void *', hence I do not include the return statement.

I can solve the problem manually but would prefer not to.

Regards,

  • 1
    Can you post an example? To my knowledge `void` is only used as a function return meaning "no return" and `void *` refers to a pointer. Hence `void` is not a type, but `void *` is. – Paul Ogilvie Jun 22 '15 at 14:10
  • Sharing your research helps everyone. Tell us what you've tried and why it didn’t meet your needs. This demonstrates that you’ve taken the time to try to help yourself, it saves us from reiterating obvious answers, and most of all it helps you get a more specific and relevant answer! Also see [how to ask](http://stackoverflow.com/questions/how-to-ask) – Eregrith Jun 22 '15 at 14:10
  • Can you rely on C11's `_Generic`? – jweyrich Jun 22 '15 at 14:35
  • The macro technique described in the answer you linked is based on token pasting, so it works as promised only for switching on macro arguments that consist of single tokens. `void *` is two tokens (even if it is spelled without any space, `void*`). – John Bollinger Jun 22 '15 at 14:39
  • I am afraid that I can't rely on C11, thanks. – user2846855 Jun 22 '15 at 14:42
  • Noted about token pasting. If there was a way to turn 'void \*' into 'void_\*' it would work. Assuming a token can contain '\*'. – user2846855 Jun 22 '15 at 14:45
  • Well, now that I think a bit more deeply, you probably won't be able to match `void` using `_Generic` anyway - cause mentioned by @Paul. – jweyrich Jun 22 '15 at 14:49
  • Note that this technique is problematic for selecting among many alternatives, as you need a macro for each one. Even if you found a workaround for the `void *` problem, you need a separate macro for every unqualified type any of your functions can return, plus one for every type qualifier used in any qualified return type. This includes not just built-in types, but also types defined in your code. – John Bollinger Jun 22 '15 at 14:58
  • The preprocessor tokenizes according to C rules. The asterisk (*) is an operator; it does not require preceding whitespace to be recognized as a separate token. – John Bollinger Jun 22 '15 at 14:59
  • If it somehow was possible to do: void##_##*. I only need to know if the type is equal to, or different from, 'void' I am only concerned with returning a value (including storing the value on the stack before return). – user2846855 Jun 22 '15 at 15:03
  • Token pasting forms *a valid token* from two others. Neither `void*` nor `void_*` is a valid token, so you cannot use token pasting to perform such a concatenation. However, you could possibly `typedef void *voidp`, and then use `voidp` consistently in place of `void *` (including in any pointer pointers, e.g. `voidp *`). – John Bollinger Jun 22 '15 at 15:10
  • This is my current solution. But I'll probably switch back to my previous solution which is to have separate macros for function returning void. I guess counting the number of tokens is not going to help either :-( – user2846855 Jun 22 '15 at 15:19
  • Thanks for all the comments, the problem seems to be unsolvable. – user2846855 Jun 22 '15 at 15:24
  • @PaulOgilvie: I know it sounds weird, but in C, `void` is considered an actual *type* (though an "underpriveliged" one). Source: http://stackoverflow.com/a/540850/3079266 –  Jun 25 '15 at 06:53
  • 1
    @Mints97, it is "linguistig haggling" as the standard uses the word `type` in an incorrect context but `void` sec is not a type. E.g.: _"A parameterlist of type void is equivalent to the empty parameter list"_ could also be said as _"A parameterlist specified as `void` means the empty parameterlist"_ (Note that in C the truely empty paramaterlist, `()` means the function can take _any number_ of parameters.) – Paul Ogilvie Jun 25 '15 at 08:29
  • @PaulOgilvie: not just "linguistic haggling"!. Even `typedef` treats it as a proper type! `typedef void VOID; VOID func(VOID) { }` works, and is a *real* `void` function! =) –  Jun 25 '15 at 08:42
  • 1
    Mints97, let's continue the haggling: `#define prm /*empty*/\n typedef void myRetVal; myRetVal func(myRetval prm) {gSideEffect++; }` sounds funny (confusing). It can be used here to enable when the type in the future changes and has some advantages over a `#define`. To define "no type" the keyword `void` is apparently necessary to be treated by the compiler as a type, but void, meaning "nothing", is only a syntactic construct with no real world effect (returning "nothing": ax register has no meaning, passing "nothing": parameter stack has no meaning). – Paul Ogilvie Jun 25 '15 at 09:58

0 Answers0