Search code examples
c++cmacrospreprocessordefinition

about ## to connect macro and invoke different functions


// file a.h

// #define MY_MACRO( size, name )
MY_MACRO( 1,    var_a )
MY_MACRO( 2,    var_b )
MY_MACRO( 3,    var_b )
MY_MACRO( 4,    var_b )
MY_MACRO( 5,    var_b )
MY_MACRO( 1024, var_c )
// file b.c

#define ARG_1( name ) fun_size_one( name )        // arg with size one
#define ARG_2( name ) fun_size_not_one( name )    // arg with size not one
#define ARG_3( name ) fun_size_not_one( name )    // arg with size not one
#define ARG_4( name ) fun_size_not_one( name )    // arg with size not one
#define ARG_5( name ) fun_size_not_one( name )    // arg with size not one
// #define ARG_...( name ) fun_size_not_one( name )    and so on

#define ARG( size, name ) ARG_##size( name )

/** here is use macro to invoke fun with different size */
#define MY_MACRO( size, name ) ARG( size, name )
#include "a.h"   // to invoke fun_size_one or fun_size_not_one

i have to define many ARG_1,2,3,4,5... to cover different size is there any way to just use 2 macros like ARG_ONE and ARG_NOT_ONE, cover these size.


Solution

  • //  Replace macro invocation with third argument.
    #define Argument3(a, b, c,...)  c
    
    /*  Select third argument, fun_size_not_one, unless x is replaced with a comma,
        which makes fun_size_one the third argument.  (There is a trailing comma
        so that the "..." in Argument3 receives at least one argument, albeit empty.)
    */
    #define Auxiliary(x)    Argument3(x, fun_size_one, fun_size_not_one,)
    
    //  Define ARG_1 to be replaced by a comma, to select fun_size_one above.
    #define ARG_1 ,
    
    //  Use the Auxiliary macro to select which function is desired.
    #define MY_MACRO( size, name ) Auxiliary(ARG_##size) (name)
    
    MY_MACRO( 1,    var_a )
    MY_MACRO( 2,    var_b )
    MY_MACRO( 3,    var_b )
    MY_MACRO( 4,    var_b )
    MY_MACRO( 5,    var_b )
    MY_MACRO( 1024, var_c )
    

    Results:

    fun_size_one (var_a)
    fun_size_not_one (var_b)
    fun_size_not_one (var_b)
    fun_size_not_one (var_b)
    fun_size_not_one (var_b)
    fun_size_not_one (var_c)