Объявление функции генерирования с использованием макроссуар
-
27-10-2019 - |
Вопрос
Я пытаюсь генерировать объявление функции, используя макрос
/* goal: generate int f(int a, float b) */
template<typename P>
struct ptype;
template<typename P>
struct ptype<void(P)> { typedef P type; };
#define NAMEe
#define COMMAe
#define COMMA ,
#define NAME(N) N PARAMS
#define PARAMS(P, ...) COMMA ## __VA_ARGS__ P NAME ## __VA_ARGS__
#define PARAM_ITER(P) P NAME
#define PROTO(R, N, P) \
ptype<void R>::type N (PARAM_ITER P (,e))
PROTO((int), f, (int)(a)(float)(b));
Это будет итеративно обработать следующее (name)
или же (type)
по NAME
или же PARAMS
соответственно, с ...
Имея пустой макроугольник. Но GCC жалуется
prototype.hpp:20:35: warning: ISO C99 requires rest arguments to be used
И Кланг жалуется на
ptype<void (int)>::type f (int aprototype.hpp:20:1: warning: varargs argument missing, but tolerated as an extension [-pedantic]
Я думаю, что это происходит из -за следующего
#define FOO(X, ...)
FOO(A);
Потому что я не передаю аргументации для ...
или каждый из них (name)
или же (type)
. Анкет Есть ли простая работа, которую я могу подать?
Теперь я использовал технику, аналогичную технике, используемой @James, чтобы найти длину списка параметров. Если как второй аргумент, вместо O
, ONT
проходит, я напечатаю запятую и NAME
. Анкет Ниже приведено окончательное решение:
/* goal: generate void f(int a, float b) */
template<typename P>
struct ptype;
template<typename P>
struct ptype<void(P)> { typedef P type; };
#define TYPE_DO(X) X
#define TYPE_DONT(X)
#define TYPE_MAYBE(X, A, ...) TYPE_D ## A (X)
#define COMMA_DO ,
#define COMMA_DONT
#define COMMA_MAYBE(A, B, ...) COMMA_D ## B
#define NAME_DO NAME
#define NAME_DONT
#define NAME_MAYBE(A, B, ...) NAME_D ## B
#define NAME(N) N PARAMS
#define PARAMS(...) COMMA_MAYBE(__VA_ARGS__,O,O) TYPE_MAYBE(__VA_ARGS__,O,O) \
NAME_MAYBE(__VA_ARGS__,O,O)
#define PARAM_ITER(P) P NAME
#define PROTO(R, N, P) \
ptype<void R>::type N (PARAM_ITER P (D,ONT))
Тест:
#define STR1(X) #X
#define STR(X) STR1(X)
int main() {
// prints correctly
std::cout << STR(PROTO((int), f, (int)(a)(float)(b)));
}
Решение
P99 есть макрос, который делает именно то, что вы хотите, я думаю, а именно P99_PROTOTYPE
. Анкет У него «подпись»
P99_PROTOTYPE(RT, NAME [, AT]*)
куда RT
это тип возврата (может быть void
) а также AT
являются типами аргументов. Список типов аргументов может быть пустым, и в этом случае он заменяется void
.
Остерегайтесь, что P99 сделан для C99, а не для C ++. Вы столкнетесь с особыми трудностями, если ваши аргументы содержат запятые. Синтаксическое злоупотребление токенами C ++ <
а также >
в качестве скопления выражений для шаблонов особенно плохо для препроцессора. C-Preprocessor и C ++ являются в основном несовместимых языками на уровне синтаксиса.
P99 уходит от трудностей, с которыми вы сталкиваетесь, обнаружив количество аргументов, которые макро получает по вызову и по -разному реагирует на пограничные чехлы.
Другие советы
Решить "FOO
«Проблема, вы можете выбрать разные макросы в зависимости от артистического пакета аргументов. Вот первый выстрел в этом:
// These need to be updated to handle more than three arguments:
#define PP_HAS_ARGS_IMPL2(_1, _2, _3, N, ...) N
#define PP_HAS_ARGS_SOURCE() MULTI, MULTI, ONE, ERROR
#define PP_HAS_ARGS_IMPL(...) PP_HAS_ARGS_IMPL2(__VA_ARGS__)
#define PP_HAS_ARGS(...) PP_HAS_ARGS_IMPL(__VA_ARGS__, PP_HAS_ARGS_SOURCE())
#define FOO_ONE(x) ONE_ARG: x
#define FOO_MULTI(...) MULTI_ARG: __VA_ARGS__
#define FOO_DISAMBIGUATE2(has_args, ...) FOO_ ## has_args (__VA_ARGS__)
#define FOO_DISAMBIGUATE(has_args, ...) FOO_DISAMBIGUATE2(has_args, __VA_ARGS__)
#define FOO(...) FOO_DISAMBIGUATE(PP_HAS_ARGS(__VA_ARGS__), __VA_ARGS__)
Пример использования:
FOO(1) // replaced by ONE_ARG: 1
FOO(1, 2) // replaced by MULTI_ARG: 1, 2
(Я постараюсь вернуться к этому, чтобы очистить его; я думаю, что там определенно есть некоторые ненужные макросы. У меня не было возможности рассмотреть более широкую проблему, которую вы описываете, поэтому я не уверен, что это решает Это тоже. Также может быть более простой способ решить эту проблему ... Я не особенно знаком с вариальными макросами. Это препараты чистого на Макпп.)