Генерирайте масив с помощта на променливи макроси

Искам да генерирам масив от указатели на функции с помощта на променлив макрос. Ето един пример.


Преди предварителна обработка:

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

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

MY_MACRO(test, a, b, c);

След предварителна обработка:

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];
}

Възможно ли е това?

По принцип трябва да имам нещо преди разширяването на масива, нещо след разширяването на масива и да добавя префикс към всеки разширен променлив макро аргумент.


person Vittorio Romeo    schedule 04.01.2014    source източник
comment
Възможно е, ако приемете определено ограничение в броя на поддържаните аргументи. Но също така е доста сложно, вижте този Q/A за малко вдъхновение :)   -  person Daniel Frey    schedule 04.01.2014
comment
Мисля, че типът трябва да е void(test::*fnPtrs[])(). Моля, моля използвайте псевдоним вместо това.   -  person dyp    schedule 04.01.2014
comment
@DyP: Използвам псевдоним в истинския код :)   -  person Vittorio Romeo    schedule 05.01.2014
comment
@DanielFrey Можете ли да публикувате коментара си като отговор? Искам да го приема   -  person Vittorio Romeo    schedule 05.01.2014
comment
Това не би било честно, не свърших почти никаква работа, освен да си спомня някои ключови думи за търсене. Ако искате да приемете отговор, той трябва да е на @DyP, използването на Boost.Preprocessor далеч не е тривиално и съм почти сигурен, че той е вложил доста работа в него.   -  person Daniel Frey    schedule 05.01.2014
comment
Добра точка. Ще приема отговора му.   -  person Vittorio Romeo    schedule 05.01.2014


Отговори (1)


Използване на библиотеката на препроцесора на boost (въпреки че има проблеми с clang++ и променливите аргументи o.O, работи добре с 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() {}

CREATE_MFPTRS(test, a,b,c,d) дава

& test :: a, & test :: b, & test :: c, & test :: d
person dyp    schedule 04.01.2014
comment
Разбира се, можете да поставите дефиницията на масива и в макрос и да извикате CREATE_MFPTR от този макрос. - person dyp; 04.01.2014