How to mimic variadic macro in VC++6.0?

2019-05-21 06:58发布

In VS2010, I wrote the following variadic macros to dump out information to files.

#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)

These macros frequently occur in my program.

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");
}

Sadly, now I have to migrate my code to the antediluvian IDE, VC++6.0, which does NOT support variadic macro. I wrote a variadic function instead.

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

But I have to change the tens if not hundreds lines of code from IND_FP(format, ...) to IND_FP(fp, indent, format, ...).

Is there any trick of macro that can help me out? Or I'd better use explicit arguments and get used to redundancy?

3条回答
Bombasti
2楼-- · 2019-05-21 07:23
#define IND_FP Logger(indent)

class Logger {
  public:
    Logger(int indent);
    int operator()(FILE* fp, char* format, ...);
  private:
    // an exercise for the reader
};
查看更多
姐就是有狂的资本
3楼-- · 2019-05-21 07:28

You could get round variadics by not using them. Use ofstream instead of FILE*. Something like this

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

Say you've declared an ofstream called logfile. For simple things, you can use

LOGGER(logfile, x);

If you wish to get more complex, you could use

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

For the indent, you could use a global

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

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

So in the same way, if you wish to indent by 3

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

C++ << is not as elegant as printf for formatting but it will get you round the problem of using variadics.

查看更多
Anthone
4楼-- · 2019-05-21 07:44
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)

This might work for your situation.

查看更多
登录 后发表回答