Home > Mobile >  Prevent comma from being interpreted as argument separator in macro called from another macro
Prevent comma from being interpreted as argument separator in macro called from another macro

Time:12-11

I have a macro which is supposed to take a function name and a list of function parameters as arguments and generate a function from that:

#include <iostream>
#include <string>
#include <array>

#define COMMA ,
#define DEFINE_FUNC(funcName,parameters,impl) \
    void funcName(parameters) impl
    
DEFINE_FUNC(
    test_func, /* function name */
    float f COMMA float f2, /* Parameters */
    {
        std::cout<<f<<","<<f2<<std::endl;
    } /* Implementation */
)


int main()
{
    test_func(1.f,2.f);
}

This compiles fine on both gcc and Visual Studio. The problem is, I now have to define an intermediary macro that relies on DEFINE_FUNC, and then use that macro for defining the function instead:

#include <iostream>
#include <string>
#include <array>

#define COMMA ,
#define DEFINE_FUNC(funcName,parameters,impl) \
    void funcName(parameters) impl

#define DEFINE_FUNC2(funcName,parameters,impl) \
    DEFINE_FUNC(funcName,parameters,impl)
    
DEFINE_FUNC2(
    test_func, /* function name */
    float f COMMA float f2, /* Parameters */
    {
        std::cout<<f<<","<<f2<<std::endl;
    } /* Implementation */
)


int main()
{
    test_func(1.f,2.f);
}

On Visual Studio this still compiles fine, but gcc refuses to compile it because the f and f2 parameters are now interpreted as separate arguments by DEFINE_FUNC2 because of the COMMA:

main.cpp:15:5: error: too many arguments provided to function-like macro invocation
    {
    ^
main.cpp:6:9: note: macro 'DEFINE_FUNC' defined here
#define DEFINE_FUNC(funcName,parameters,impl) \
        ^
main.cpp:12:1: error: unknown type name 'DEFINE_FUNC'
DEFINE_FUNC2(
^
main.cpp:10:5: note: expanded from macro 'DEFINE_FUNC2'
    DEFINE_FUNC(funcName,parameters,impl)
    ^

I could just copy the contents of DEFINE_FUNC into DEFINE_FUNC2, but this is a very simplified example and it would cause significant redundancy in the actual code.

I tried changing float f COMMA float f2 to (float f,float f2) to force the preprocessor to ignore the comma, but that also fails to compile:

#define COMMA ,
#define DEFINE_FUNC(funcName,parameters,impl) \
    void funcName##parameters impl

#define DEFINE_FUNC2(funcName,parameters,impl) \
    DEFINE_FUNC(funcName,parameters,impl)
    
DEFINE_FUNC2(
    test_func, /* function name */
    (float f , float f2), /* Parameters */
    {
        std::cout<<f<<","<<f2<<std::endl;
    } /* Implementation */
)

Error:

main.cpp:12:1: error: pasting formed 'test_func(', an invalid preprocessing token
DEFINE_FUNC2(
^

Is there some way to make this work with both gcc and Visual Studio?

CodePudding user response:

Your last solution is mostly valid, but in a function definition, the function name and parameters do not form a single token, so you should not join them using ##:

#define DEFINE_FUNC(funcName,parameters,impl) \
    void funcName parameters impl
  • Related