Генерация нескольких вызовов макросов в соответствии с количеством аргументов

Я пытаюсь вызвать эту функцию несколько раз в каче ственном режиме.

template<class T>
void METADATA_METHODS_IMPL(std::string& metadata, const T &value, const std::string &key)
{
metadata += boost::format("%1%:%2%") % key % value();
}

Я написал следующий макрос:

#define METADATA_METHODS_IMPL_1(md, v1)\
METADATA_METHODS_IMPL(md, v1, #v1);

#define METADATA_METHODS_IMPL_2(md, v1, v2)\
METADATA_METHODS_IMPL_1(md, v1)\
METADATA_METHODS_IMPL_1(md, v2)

#define METADATA_METHODS_IMPL_3(md, v1, v2, v3)\
METADATA_METHODS_IMPL_2(md, v1, v2)\
METADATA_METHODS_IMPL_1(md, v3)

и так далее …

Мне нужно позвонить METADATA_METHODS_IMPL_N где N это ряд аргументов в __VA_ARGS__

#define METADATA_METHODS(...)\
std::string METADATA_METHODS_IMPL_FUNC()\
{\
std::string metadata;\
BOOST_PP_OVERLOAD(METADATA_METHODS_IMPL_,__VA_ARGS__)(metadata, __VA_ARGS__)\
return metadata;\
}

Код выше (с BOOST_PP_OVERLOAD) дает мне неподходящий результат:

class X
{
std::string F1();
std::string F2();
std::string F3();

METADATA_METHODS(F1, F2, F3);
};

Это приводит к

std::string METADATA_METHODS_IMPL_FUNC()
{
std::string metadata;
METADATA_METHODS_IMPL(metadata, F1, F2, F3, "F1", "F2", "F3");
METADATA_METHODS_IMPL(metadata, , "");
METADATA_METHODS_IMPL(metadata, , "");
return metadata;
};

И я хочу что-то вроде этого:

std::string METADATA_METHODS_IMPL_FUNC()
{
std::string metadata;
METADATA_METHODS_IMPL(metadata, F1, "F1");
METADATA_METHODS_IMPL(metadata, F2, "F2");
METADATA_METHODS_IMPL(metadata, F3, "F3");
return metadata;
};
  • Кто-нибудь знает, как добиться желаемого результата?
  • Могу ли я использовать Boost.preprocessor библиотека для автоматического создания METADATA_METHODS_IMPL_K для некоторых K in [1 .. 10] с помощью METADATA_METHODS_IMPL_1

0

Решение

Используя эти макросы, мы можем заставить препроцессор продолжать повторное сканирование и допускать рекурсивные макросы.

#define EVAL(...)  EVAL3(EVAL3(EVAL3(__VA_ARGS__)))
#define EVAL3(...) EVAL2(EVAL2(EVAL2(__VA_ARGS__)))
#define EVAL2(...) EVAL1(EVAL1(EVAL1(__VA_ARGS__)))
#define EVAL1(...) EVAL0(EVAL0(EVAL0(__VA_ARGS__)))
#define EVAL0(...) __VA_ARGS__

Мы можем определить некоторые вспомогательные функции для построения концепций.

#define CAT(a, ...) PRIMITIVE_CAT(a,__VA_ARGS__)
#define PRIMITIVE_CAT(a, ...) a ## __VA_ARGS__

#define EMPTY()
#define EAT(...)
#define IDENT(...) __VA_ARGS__
#define DEFER(id) id EMPTY()
#define OBSTRUCT(...) __VA_ARGS__ DEFER(EMPTY)()

#define I_TRUE(t,f) t
#define I_FALSE(t,f) f
#define I_IS_DONE(a,b,...) b
#define TRUE_DONE() ~, I_TRUE
#define IS_DONE(b) OBSTRUCT(I_IS_DONE)(CAT(TRUE_,b)(),I_FALSE)

И создайте эту функцию Macro Mapping, которая передает первый параметр каждому.

#define MM() MM_CALL
#define MM_NEXT(Macro,md,a,...) \
IS_DONE(a)(                    \
EAT                          \
,                                \
OBSTRUCT(MM)()                 \
)                                  \
(Macro,md,a,__VA_ARGS__)
#define MM_CALL(Macro,md,a,...)   \
Macro(md,a)                      \
MM_NEXT(Macro,md,__VA_ARGS__)
#define MacroMap(Macro,md,...) EVAL(MM_CALL(Macro,md,__VA_ARGS__,DONE))

После определения реализации связанных функций

#define METADATA_METHODS_IMPL_MACRO(md,a) \
METADATA_METHODS_IMPL(md, a, #a);

#define METADATA_METHODS(md,...) \
MacroMap(METADATA_METHODS_IMPL_MACRO,md,__VA_ARGS__) \
return md

Это:

METADATA_METHODS(metadata, F1, F2, F3);

Результаты в этом (после добавления некоторого форматирования):

METADATA_METHODS_IMPL(metadata, F1, "F1");
METADATA_METHODS_IMPL(metadata, F2, "F2");
METADATA_METHODS_IMPL(metadata, F3, "F3");
return metadata;
0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]