Preprocessor trick?

Discussion in 'C++' started by SerGioGio, Jan 22, 2005.

  1. SerGioGio

    SerGioGio Guest

    Hello,

    Is there a way to #define a (set of) macro that will turn:
    FUNC(a)(b)(c)
    into:
    func(a, b, c)
    regardless of the number of parameters?

    i.e:
    FUNC(a)(b)(c) ---> func(a, b, c)
    FUNC(a)(b) ---> func(a, b)
    FUNC(a) ---> func(a)

    Despite my efforts I can't find one so I am wondering whether there actually
    is.

    Thanks in advance!

    SerGioGio
     
    SerGioGio, Jan 22, 2005
    #1
    1. Advertising

  2. SerGioGio wrote:
    > Hello,
    >
    > Is there a way to #define a (set of) macro that will turn:
    > FUNC(a)(b)(c)
    > into:
    > func(a, b, c)
    > regardless of the number of parameters?
    >
    > i.e:
    > FUNC(a)(b)(c) ---> func(a, b, c)
    > FUNC(a)(b) ---> func(a, b)
    > FUNC(a) ---> func(a)
    >
    > Despite my efforts I can't find one so I am wondering whether there

    actually
    > is.
    >
    > Thanks in advance!
    >
    > SerGioGio


    NO!
     
    puzzlecracker, Jan 22, 2005
    #2
    1. Advertising

  3. SerGioGio

    Mike Wahler Guest

    "SerGioGio" <> wrote in message
    news:41f1a9fa$...
    > Hello,
    >
    > Is there a way to #define a (set of) macro that will turn:
    > FUNC(a)(b)(c)
    > into:
    > func(a, b, c)
    > regardless of the number of parameters?
    >
    > i.e:
    > FUNC(a)(b)(c) ---> func(a, b, c)
    > FUNC(a)(b) ---> func(a, b)
    > FUNC(a) ---> func(a)
    >
    > Despite my efforts I can't find one so I am wondering whether there

    actually
    > is.


    I'm not sure, but I've seen some rather clever tricks done
    with macros. BUT: I wouldn't even try, because:
    Why do you want to do this? Macros don't allow for the level of
    type saftey and error checking that functions do (all they are
    is a text-substitution mechanism). Their necessity is much less
    in C++ than in C. Especially in the context you ask about,
    because C++ has function overloading and default parameters.


    Overloaded functions:

    /* A */ void func(int a){}
    /* B */ void func(int a, int b){}
    /* C */ void func(int a, int b, int c){}

    int main()
    {
    func(1); /* calls version A */
    func(1, 2); /* calls version B */
    func(1, 2, 3); /* calls version C */
    return 0;
    }

    Default paramters:

    void func(int a = 0, int b = 0, int c = 0){}

    int main()
    {
    func(); /* same as func(0, 0, 0); */
    func(1); /* same as func(1, 0, 0); */
    func(1, 2); /* same as func(1, 2, 0); */
    func(1, 2, 3);
    return 0;
    }

    (The defaults can be any values you want, and the
    function need not refer to any parameters not
    applicable to a particular call).

    -Mike
     
    Mike Wahler, Jan 22, 2005
    #3
  4. "SerGioGio" <> wrote...
    > Hello,
    >
    > Is there a way to #define a (set of) macro that will turn:
    > FUNC(a)(b)(c)
    > into:
    > func(a, b, c)
    > regardless of the number of parameters?
    >
    > i.e:
    > FUNC(a)(b)(c) ---> func(a, b, c)
    > FUNC(a)(b) ---> func(a, b)
    > FUNC(a) ---> func(a)
    >
    > Despite my efforts I can't find one so I am wondering whether there
    > actually
    > is.


    Well, it's relatively simple to prove that there can be no such macro.
    If you write

    FUNC(a)(b)

    why should the preprocessor continue looking ahead for (b), when it can
    stop right there and simply substitute FUNC(a) with func(a)? So, the
    preprocessor cannot decide, I guess.

    You can simulate this with C++, though. By overloading operator() and
    defining what value it returns, you probably could make it so if you
    write

    func1(a)(b)(c)

    it actually eventually calls some func(a,b,c)... I'll leave it for you
    to try.

    V
     
    Victor Bazarov, Jan 22, 2005
    #4
  5. "SerGioGio" <> wrote in message
    news:41f1a9fa$...
    > Hello,
    >
    > Is there a way to #define a (set of) macro that will turn:
    > FUNC(a)(b)(c)
    > into:
    > func(a, b, c)
    > regardless of the number of parameters?
    >
    > i.e:
    > FUNC(a)(b)(c) ---> func(a, b, c)
    > FUNC(a)(b) ---> func(a, b)
    > FUNC(a) ---> func(a)


    Victor's argument that it can't be done sounds right, but my intuitions about
    the preprocessor are often wrong.

    It can *almost* be done, though, using the Boost Preprocessor Metaprogramming
    library:

    Program:

    #include <boost/preprocessor/seq/enum.hpp>

    #define FUNC(seq) func(BOOST_PP_SEQ_ENUM(seq))

    FUNC((a))
    FUNC((a)(b))
    FUNC((a)(b)(c))

    Preprocessed output:

    func(a)
    func(a, b)
    func(a, b, c)

    > SerGioGio


    Jonathan
     
    Jonathan Turkanis, Jan 22, 2005
    #5
  6. SerGioGio

    Alan Krueger Guest

    SerGioGio wrote:
    > Is there a way to #define a (set of) macro that will turn:
    > FUNC(a)(b)(c)
    > into:
    > func(a, b, c)
    > regardless of the number of parameters?


    The specific example with three parameters might be constructed like this:

    #define A(x) x)
    #define B(x) x,A
    #define SUM(x) sum(x,B

    int sum( int a, int b, int c )
    {
    return a + b + c;
    }

    int a = 2;
    int b = 3;
    int c = 5;
    int s = SUM(a)(b)(c);

    Not sure if iterative replacement is standard, or just supported by the
    compiler I'm using, but this last line gets transformed to

    int s = sum(a,b,c);

    Doing this for *any* number of parameters with a single set of macros is
    unlikely, because you'd have to use a recursive macro, which cannot be
    propertly terminated.
     
    Alan Krueger, Jan 22, 2005
    #6
  7. SerGioGio

    SerGioGio Guest

    >
    > I'm not sure, but I've seen some rather clever tricks done
    > with macros. BUT: I wouldn't even try, because:
    > Why do you want to do this? Macros don't allow for the level of
    > type saftey and error checking that functions do (all they are
    > is a text-substitution mechanism). Their necessity is much less
    > in C++ than in C. Especially in the context you ask about,
    > because C++ has function overloading and default parameters.
    >


    Actually I would like to get the text of the arguments, not only their
    values...
    so I can only use a macros and #x command.
    This could be achieved using a FUNC(a, b, c) macro but the FUNC(a)(b)(c)
    form suits more to the purpose.

    SerGioGio
     
    SerGioGio, Jan 22, 2005
    #7
  8. SerGioGio

    SerGioGio Guest

    > Not sure if iterative replacement is standard, or just supported by the
    > compiler I'm using, but this last line gets transformed to
    >
    > int s = sum(a,b,c);
    >
    > Doing this for *any* number of parameters with a single set of macros is
    > unlikely, because you'd have to use a recursive macro, which cannot be
    > propertly terminated.


    Yes, it really looks like doing it for any number of parameters is
    impossible.
    I tried the following:

    #define FUNC2(x) func(dummy FUNC2_END_A(x)
    #define FUNC2_END_A(x) ,x FUNC2_END_B
    #define FUNC2_END_B(x) ,x FUNC2_END_A

    which does:

    FUNC2(a)(b)(c) --> func(dummy ,a ,b ,c FUNC2_END_B
    FUNC2(a)(b) --> func(dummy ,a ,b FUNC2_END_A
    FUNC2(a) --> func(dummy ,a FUNC2_END_B

    unfortunately there is no way to transform subsequentely... FUNC2_END_A and
    FUNC2_END_B into )

    The solution I am now considering is doing:

    enum FUNC6_END { FUNC6_END_A, FUNC6_END_B };
    #define FUNC6(x) func* FUNC6_END_A(x)
    #define FUNC6_END_A(x) (x)*(#x)*FUNC6_END_B
    #define FUNC6_END_B(x) (x)*(#x)*FUNC6_END_A

    which does:

    FUNC6(a)(b)(c) --> func*(a)*(#a)*(b)*(#b)*(c)*(#c)*FUNC6_END_A
    FUNC6(a)(b) --> func*(a)*(#a)*(b)*(#b)*FUNC6_END_B
    FUNC6(a) --> func*(a)*(#a)*FUNC6_END_A

    As you can see, my aim is to get the text and values of all the "arguments"
    of the macro FUNC6, and that is why I can't just use overload operator().

    This solution requires slightly more complicated code, possibly slighlty
    slower, and there may be a problem with the precedence of operators. But it
    looks its the closest solution.

    SerGioGio
     
    SerGioGio, Jan 22, 2005
    #8
  9. SerGioGio wrote:
    > #define FUNC2(x) func(dummy FUNC2_END_A(x)
    > #define FUNC2_END_A(x) ,x FUNC2_END_B
    > #define FUNC2_END_B(x) ,x FUNC2_END_A


    enum FUNC_END { FUNC2_END_A, FUNC2_END_B }
    #define FUNC2(x) func(FUNC2_END_A(x)
    #define FUNC2_END_A(x) x, FUNC2_END_B
    #define FUNC2_END_B(x) x, FUNC2_END_A

    > FUNC2(a)(b)(c) --> func(dummy ,a ,b ,c FUNC2_END_B
    > FUNC2(a)(b) --> func(dummy ,a ,b FUNC2_END_A
    > FUNC2(a) --> func(dummy ,a FUNC2_END_B


    FUNC2(a)(b)(c)) --> func(a, b, c, FUNC2_END_B)
    FUNC2(a)(b)) --> func(a, b, FUNC2_END_A)
    FUNC2(a)) --> func(a, FUNC2_END_B)

    If you
    #define FUNC3(x) FUNC2 x )
    it should be possible to write FUNC3((a)(b)(c)), which looks
    much nicer ;)

    A different approach:

    extern class func_t
    {
    public:
    func_t() :
    FUNC_END_A(*this), FUNC_END_B(*this) {}

    template<class T>
    func_t& operator()(const ::std::pair<T, const char*>& param)
    {
    std::cout << param.second << ": " <<
    param.first << "\n";
    return *this;
    }

    func_t& FUNC_END_A;
    func_t& FUNC_END_B;

    } func;

    #define FUNC func.FUNC_END_A
    #define FUNC_END_A(x) FUNC_END_A:):std::make_pair(x, #x)).FUNC_END_B
    #define FUNC_END_B(x) FUNC_END_B:):std::make_pair(x, #x)).FUNC_END_A

    // in some cpp file
    func_t func;

    int main()
    {
    int a = 0, b = 1, c = 2;
    FUNC(a)(b)(c);
    FUNC(a)(b);
    FUNC(a);
    }

    --
    Regards,
    Tobias
     
    =?ISO-8859-1?Q?Tobias_G=FCntner?=, Jan 22, 2005
    #9
  10. SerGioGio wrote:
    > Hello,
    >
    > Is there a way to #define a (set of) macro that will turn:
    > FUNC(a)(b)(c)
    > into:
    > func(a, b, c)
    > regardless of the number of parameters?
    >
    > i.e:
    > FUNC(a)(b)(c) ---> func(a, b, c)
    > FUNC(a)(b) ---> func(a, b)
    > FUNC(a) ---> func(a)
    >
    > Despite my efforts I can't find one so I am wondering whether there actually
    > is.
    >
    > Thanks in advance!
    >
    > SerGioGio
    >
    >


    I believe a better design would be to pass a structure
    to the function that contains information about the
    parameters, such as quantity, locations and type.

    enum Parameter_Type
    {
    PT_CHAR, PT_UCHAR, PT_INT, PT_UINT,
    PT_DOUBLE, PT_FLOAT, PT_LONG
    };

    struct Param_Attributes
    {
    enum Parameter_Type type;
    void * pointer_to_data;
    }

    void Process_Parameters(struct Param_Attributes * array,
    size_t quantity)
    {
    /* ... */
    }

    The idea here is that one function is used for multiple
    data types versus one function for each quantity and
    variation of types.

    Just a thought...

    --
    Thomas Matthews

    C++ newsgroup welcome message:
    http://www.slack.net/~shiva/welcome.txt
    C++ Faq: http://www.parashift.com/c -faq-lite
    C Faq: http://www.eskimo.com/~scs/c-faq/top.html
    alt.comp.lang.learn.c-c++ faq:
    http://www.comeaucomputing.com/learn/faq/
    Other sites:
    http://www.josuttis.com -- C++ STL Library book
    http://www.sgi.com/tech/stl -- Standard Template Library
     
    Thomas Matthews, Jan 22, 2005
    #10
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Nuri Yilmaz

    A .Net trick everyday!

    Nuri Yilmaz, Jul 28, 2004, in forum: ASP .Net
    Replies:
    0
    Views:
    403
    Nuri Yilmaz
    Jul 28, 2004
  2. Nuri YILMAZ

    A .Net trick everday!

    Nuri YILMAZ, Aug 9, 2004, in forum: ASP .Net
    Replies:
    0
    Views:
    444
    Nuri YILMAZ
    Aug 9, 2004
  3. Cronus
    Replies:
    1
    Views:
    677
    Paul Mensonides
    Jul 15, 2004
  4. Preprocessor trick

    , Nov 22, 2006, in forum: C++
    Replies:
    6
    Views:
    507
    Pete Becker
    Nov 23, 2006
  5. Lola

    preprocessor trick

    Lola, Feb 10, 2011, in forum: C Programming
    Replies:
    4
    Views:
    589
    Thad Smith
    Feb 12, 2011
Loading...

Share This Page