1

I want to generate an array of function pointers using a variadic macro. Here's an example.


Before preprocessing:

#define MY_MACRO(mClassName, ...) ???

struct test { 
    void a() { }
    void b() { }
    void c() { }
};

MY_MACRO(test, a, b, c);

After preprocessing:

struct test { 
    void a() { }
    void b() { }
    void c() { }
};

void(test::*)() getMemFnPtr(int mIdx) {
    static void(test::*)() fnPtrs[]{
        &test::a,
        &test::b,
        &test::c
    };
    return fnPtrs[mIdx];
}

Is this possible?

Basically, I need to have something before the array expansion, something after the array expansion, and add a prefix to every expanded variadic macro argument.

tshepang
  • 12,111
  • 21
  • 91
  • 136
Vittorio Romeo
  • 90,666
  • 33
  • 258
  • 416
  • 1
    It's possible if you accept a certain limit in the number of supported arguments. But it's also quite complicated, see [this Q/A](http://stackoverflow.com/questions/1872220) for some inspiration :) – Daniel Frey Jan 04 '14 at 18:16
  • I think the type should be `void(test::*fnPtrs[])()`. Please, *please* use an alias instead. – dyp Jan 04 '14 at 19:49
  • @DyP: I'm using an alias in the real code :) – Vittorio Romeo Jan 04 '14 at 20:16
  • @DanielFrey Can you post your comment as an answer? I want to accept it – Vittorio Romeo Jan 04 '14 at 21:43
  • 1
    That wouldn't be fair, I did almost no work except remembering some keywords to search for. If you want to accept an answer, it should be @DyP's, using Boost.Preprocessor is far from trivial and I'm pretty sure he put quite some work into it. – Daniel Frey Jan 04 '14 at 21:46

1 Answers1

3

Using boost's preprocessor library (though having problems with clang++ and the variadic arguments o.O, works fine with g++):

#include <boost/preprocessor/facilities/expand.hpp>
#include <boost/preprocessor/seq/transform.hpp>
#include <boost/preprocessor/seq/enum.hpp>
#include <boost/preprocessor/variadic/to_seq.hpp>

#define CREATE_MFPTR(s, data, elem) \
    & BOOST_PP_EXPAND(data) :: BOOST_PP_EXPAND(elem)

#define CREATE_MFPTRS(class_name, ...)                                  \
    BOOST_PP_SEQ_ENUM(                                                  \
        BOOST_PP_SEQ_TRANSFORM(CREATE_MFPTR,                            \
                               class_name,                              \
                               BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__))   \
    )                                                                   // end



struct test
{
    void a();
    void b();
    void c();
    void d();
};

using MFPtr = void (test::*)();
MFPtr arr[] = {
    CREATE_MFPTRS(test, a,b,c,d)
};

int main() {}

the CREATE_MFPTRS(test, a,b,c,d) yields

& test :: a, & test :: b, & test :: c, & test :: d
dyp
  • 38,334
  • 13
  • 112
  • 177
  • Of course, you can put the array definition in a macro, too, and call `CREATE_MFPTR` from within that macro. – dyp Jan 04 '14 at 19:53