18

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

14
  • 1
    What do you want the macro to expand to? It doesn't make sense to paste a period and an identifier together.
    – aschepler
    Commented Sep 22, 2017 at 3:12
  • 4
    Can't you use PolicyObject1.FuncName instead of PolicyObject1.##FuncName? That is just straight macro substitution: nothing fancy. Alternatively, why not use templates. - They are a lot easier to debug.
    – cup
    Commented Sep 22, 2017 at 3:14
  • 1
    C and C++ are different languages. Choose one. Commented Sep 22, 2017 at 3:21
  • 1
    @Nitesh: C and C++ rules are subtly different in some ways. I don't think those differences affect your question, but I can't be 100% sure of that. Presumably you're using either a C compiler or a C++ compiler to compile your code. That determines whether your question should be tagged c or c++. Commented Sep 22, 2017 at 3:35
  • 1
    @Nitesh: "but a lot is common and I consider macro to be one of them" -- Just for future reference, the C standard specifies the preprocessor in section 6.10, and the C++ standard specifies its preprocessor in section 16. Have you compared those specifications and confirmed that they're compatible? Quite possibly they are, but by limiting your question to one language or the other you reduce the number of things you and people trying to help you need to worry about. Commented Sep 22, 2017 at 15:36

2 Answers 2

43

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.

1
  • Thnx. Was missing wood for forest.
    – Nitesh
    Commented Sep 26, 2017 at 7:31
6

delete "##".

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.