Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pasting formed an invalid processing token '.'

I am trying to use macro for calling appropriate object based on the type.

#define DELEGATE_FUNC(FuncName, kind, paramPtr)         \
    if (kind == 1) {                                    \
        return PolicyObject1.##FuncName(paramPtr);      \
    }                                                   \
    else {                                              \
        return PolicyObject2.##FuncName(paramPtr);      \
    }                                                   \
    return 0;                                           \

(PolicyObject1 & PolicyObject2 are two static objects.) Now when using the macro, e.g.

DELEGATE_FUNC(ProcessPreCreate, 1, null_ptr);

It compiles fine in VS 2015, but gives error with LLVM "Pasting formed an invalid processing token '.ProcessPreCreate'"

I looked for, and found a few posts and understood it up to some level - Need double level of indirection, e.g. Why do I need double layer of indirection for macros?

However I am unable to define those two layers of macro, can anyone help?

(Please leave aside the discussion on design aspects)

Thanks

like image 788
Nitesh Avatar asked Sep 22 '17 03:09

Nitesh


2 Answers

When the compiler reads your C++ file, one of the first steps is dividing it into tokens like identifier, string literal, number, punctuation, etc. The C preprocessor works on these tokens, not on text. The ## operator glues tokens together. So, for example, if you have

#define triple(foo) foo##3

Then triple(x) will get you the identifier x3, triple(12) will get you the integer 123, and triple(.) will get you the float .3.

However, what you have is .##FuncName, where FuncName is ProcessPreCreate. This creates the single token .ProcessPreCreate, which is not a valid C++ token. If you had typed PolicyObject1.ProcessPreCreate directly instead of through a macro, it would be tokenized into three tokens: PolicyObject1, ., and ProcessPreCreate. This is what your macro needs to produce in order to give valid C++ output.

To do that, simply get rid of the ##. It is unnecessary to glue the . to the FuncName, because they are separate tokens. To check this, you can put a space between a . and a member name; it will still compile just fine. Since they are separate tokens, they should not and cannot be glued together.

like image 156
Daniel H Avatar answered Oct 19 '22 23:10

Daniel H


delete "##".

#define DELEGATE_FUNC(FuncName, kind, paramPtr)     \
if (kind == 1) {                                    \
    return PolicyObject1.FuncName(paramPtr);        \
}                                                   \
else {                                              \
    return PolicyObject2.FuncName(paramPtr);        \
}                                                   \
return 0;                                           \
like image 35
shede333 Avatar answered Oct 19 '22 22:10

shede333