Как имитировать вариативный макрос в VC++6.0?

В VS2010 я написал следующие вариативные макросы для вывода информации в файлы.

#define INDENT(fp, indent) for(size_t __i = 0; __i < (indent); ++__i) fprintf((fp), "  ")
// IND_FP = indented fprintf.
// This macro uses two IMPLICIT parameters.
// 1. (FILE *)fp is a pointer to the output file.
// 2. (size_t)indent specifies the indentation level.
#define IND_FP(format, ...) do{ INDENT(fp, indent); fprintf(fp, format, __VA_ARGS__); }while(0)

Эти макросы часто встречаются в моей программе.

void CMAP::dump_info(FILE *fp, size_t indent){
  IND_FP("<cmap tableVersion=\"0x%08x\" numberOfEncodingTables=\"%d\">\n",
    table_version_number, num_encoding_tables);
  //...
  IND_FP("</cmap>\n");
}

К сожалению, теперь мне приходится переносить свой код в допотопную IDE, VC++6.0, которая НЕ поддерживает вариативный макрос. Вместо этого я написал вариативную функцию.

void IND_FP(FILE *fp, size_t indent, char *format, ...){
  INDENT(fp, indent);
  va_list arg_ptr;
  va_start(arg_ptr, format);
  vfprintf(fp, format, arg_ptr);
  va_end(arg_ptr);
}

Но мне нужно изменить десятки, если не сотни строк кода с IND_FP(format, ...) на IND_FP(fp, indent, format, ...).

Есть ли какой-нибудь трюк с макросом, который может мне помочь? Или мне лучше использовать явные аргументы и привыкнуть к избыточности?


person lzl124631x    schedule 25.05.2014    source источник
comment
О, мальчик, ты определенно мигрируешь в неправильном направлении. По какой именно причине вам нужно использовать VC++ 6? Может быть, это можно обойти, используя современный компилятор?   -  person Cody Gray    schedule 25.05.2014
comment
@КодиГрей. Мой профессор пользуется VC++6.0. Он хоть и легкий и крошечный, а VS2010 кажется слишком громоздким. Поэтому я должен перенести свой код при отправке. Я попытаюсь его уговорить, но человек в его возрасте склонен к упрямству.   -  person lzl124631x    schedule 25.05.2014
comment
Запуск cl.exe из командной строки еще более легкий и крошечный. Ему вообще не нужно открывать ваш код в IDE! Серьезно, ваш аргумент не должен заключаться в том, что вам больше нравится использовать какую-то конкретную среду разработки. Как и большинству разработчиков C++, мне тоже нравилась среда VC++6. Проблема и аргумент, который вам нужно привести, заключается в том, что компилятор, с которым он связан, буквально слишком стар, чтобы научить вас полезным современным практикам C++.   -  person Cody Gray    schedule 25.05.2014
comment
@КодиГрей. Спасибо. Этот аргумент более убедителен, и я хотел бы поделиться им со своим профессором. В любом случае, мне все еще любопытно, можно ли обойти эту проблему в VC++6.   -  person lzl124631x    schedule 25.05.2014


Ответы (3)


Вы можете обойти вариады, не используя их. Использование потока вместо FILE*. Что-то вроде этого

#define LOGGER(logfile,loginfo)  logfile << loginfo << std::endl

Скажем, вы объявили поток с именем logfile. Для простых вещей вы можете использовать

LOGGER(logfile, x);

Если вы хотите получить более сложный, вы можете использовать

LOGGER(logfile, "x = " << x << "  b=" << b);

Для отступа вы можете использовать глобальный

// declaration
char spaces[128];
...
// Initialization
memset(spaces, ' ', sizeof(spaces));

#define LOGGER(logfile,indent,loginfo) \
    spaces[indent] = '\0'; \
    logfile << spaces << loginfo << std::endl; \
    spaces[indent] = ' '

Таким же образом, если вы хотите сделать отступ на 3

LOGGER(logfile, 3, "x=" << x << "   y=" << y << "   z=" << z);

C++ ‹‹ не так элегантен, как printf для форматирования, но он поможет вам обойти проблему использования переменных переменных.

person cup    schedule 25.05.2014

FILE *g_fp;
size_t g_indent;

void ind_fp(char *format, ...){
  INDENT(g_fp, g_indent);
  va_list arg_ptr;
  va_start(arg_ptr, format);
  vfprintf(g_fp, format, arg_ptr);
  va_end(arg_ptr);
}

#define IND_FP (g_fp = fp, g_indent = indent, &ind_fp)

Это может сработать в вашей ситуации.

person Zhang Boyang    schedule 24.08.2017

person    schedule
comment
Сказав это, я бы не рекомендовал это в серьезной разработке, так же как я бы вообще не рекомендовал никаких макросов. Или ваш стиль ведения журнала на основе printf. Или ВК6. Или, судя по всему, ваш профессор. - person n. 1.8e9-where's-my-share m.; 25.05.2014