Как добавить параметр в вызов функции форматированной строки через функцию #define - PullRequest
2 голосов
/ 08 сентября 2010

Я хочу создать макросы, которые будут вставлять параметр в вызов функции.Например, у меня есть функция Action(), объявленная ниже.Действие принимает в качестве входных данных перечисление для номера состояния и форматированную строку с необязательными аргументами для строки.

Я хочу определить макросы так, чтобы вместо вызова Action( ActionState1, "someText %d", &arg) с ActionState1 для параметра состояния я мог просто вызвать State1("someText %d", &arg).Таким образом, макрос вставит в ActionState1 параметр состояния для меня.Я думаю о чем-то вроде следующего:

#define State1(formatedString, ...) Action(ActionState1, formatedString, ...)
#define State2(formatedString, ...) Action(ActionState2, formatedString, ...)
#define State3(formatedString, ...) Action(ActionState3, formatedString, ...)

enum {
  ActionState1,
  ActionState2,
  ActionState3
}

static void Action( State state, String formatedString, ...);

Кто-нибудь знает, какой будет правильный формат для этого?

Ответы [ 3 ]

2 голосов
/ 08 сентября 2010

Я считаю, что __VA_ARGS__ - это то, что вы ищете:

#define State1(formattedString, ...) Action(1, (formattedString), __VA_ARGS__)
 .
 .
 .

Это функция C99, и Википедия утверждает , что они не являются частью какого-либо официального стандарта C ++ (отмечу это, поскольку вы используете тег C ++), но являются довольно популярным расширением. На этом вопросе есть хорошее обсуждение .

2 голосов
/ 08 сентября 2010

Нет, это невозможно сделать с помощью препроцессора.Препроцессор позволяет вам связывать сущности, но не наоборот.Для того, что вы хотите, вам нужно будет разбить State1 на два компонента State и 1 (последний важнее) и продолжить вызов.

Однако, более важный вопроспочему вы хотите это сделать?Вы вряд ли сохраните набор текста с помощью такого преобразования или получите удобочитаемость.

Вы можете получить что-то поблизости, используя шаблоны, хотя:1013 * Но опять же, здесь почти нет синтаксической выгоды ИМО.

0 голосов
/ 08 сентября 2010

Почему вы хотите создать такую ​​вещь? В C ++ предпочитайте использовать потоковые операторы или аналогичные по сравнению с использованием varargs, поскольку это обеспечивает безопасность типов среди прочего.

Я не верю, что есть какой-либо способ делать то, что вы хотите в макросах препроцессора C ++. Если у вас была версия Action va_list, вы могли бы получить что-то вроде следующего, но я, кажется, напомню, что параметр перед ... должен быть POD - к сожалению, быстрый поиск не может подтвердить или опровергнуть это. .

#include <cstdarg>
inline void State1(String formatedString, ...)
{
    va_list args;
    va_start(args, formatedString);
    Action(1, formatedString, args);
    va_end(args);
}
...