Using commas inside a macro without parenthesis: How can I mix and match with a template?

后端 未结 3 1323
终归单人心
终归单人心 2020-12-09 21:57

Consider a simple macro:

#define ECHO(x) x

ECHO(foo(1, 2))

This produces the exact output we expect:

foo(1, 2)


        
相关标签:
3条回答
  • 2020-12-09 22:00
    #define COMMA ,
    ECHO(template<int COMMA bool>)
    

    A little painful, but it works.

    FWIW, if the syntax for the argument allows ()s, you don't need the substitution, e.g.,

    ECHO((a, b))
    

    will work for a single argument macro but that doesn't work in all cases (including yours).

    0 讨论(0)
  • 2020-12-09 22:09

    A variadic macro may help:

    #define ECHO(x...) x
    
    ECHO(foo(1, 2))
    ECHO(template<int, bool>)
    
    0 讨论(0)
  • 2020-12-09 22:15

    if you allow usage of Cog in your project, your code becomes more readable:

    /*[[[cog
    # definitions ----
    import cog
    
    def AddDeclaration( templateArg , restOfDeclaration ):
        cog.outl(' %s struct %s; ' % (templateArg , restOfDeclaration))
    
    # generation ---
    types = ['bool' , 'std::string']
    names = ['Foo' , 'Bar']
    for index in range(len(names)):
        AddDeclaration( 'template<int, %s>' % types[index] , names[index])
    ]]]*/
    //[[[end]]]
    

    After you run cog over this file, you'll get:

    /*[[[cog
    # definitions ----
    import cog
    
    def AddDeclaration( templateArg , restOfDeclaration ):
        cog.outl(' %s struct %s; ' % (templateArg , restOfDeclaration))
    
    # generation ---
    types = ['bool' , 'std::string']
    names = ['Foo' , 'Bar']
    for index in range(len(names)):
        AddDeclaration( 'template<int, %s>' % types[index] , names[index])
    ]]]*/
    template<int, bool> struct Foo; <---------------- generated by Cog!!
    template<int, std::string> struct Bar;
    //[[[end]]]
    

    You can even move your definitions in separate .py files and the cog section will look like:


    declarations.py

    import cog
    
    def AddDeclaration( templateArg , restOfDeclaration ):
        cog.outl(' %s struct %s; ' % (templateArg , restOfDeclaration))
    

    my.h

    /*[[[cog
    # definitions ----
    import declarations
    # generation ---
    types = ['bool' , 'std::string']
    names = ['Foo' , 'Bar']
    for index in range(len(names)):
        AddDeclaration( 'template<int, %s>' % types[index] , names[index])
    ]]]*/
    template<int, bool> struct Foo;
    template<int, std::string> struct Bar;
    //[[[end]]]
    

    the main advantage of using cog is that you gain complete control of your code generation, completely avoid unreadable messes using boost preprocessor or stuff like that.

    the main disadvantage is that you add a new tool dependency to your project, also since you need to wrap its usage in comments with the cog section markers, it might actually be worse than writing the code manually for small usages. It really pays off when you need to declare big enums or lot of unavoidable boilerplate code

    0 讨论(0)
提交回复
热议问题