【问题标题】:How to mimic variadic macro in VC++6.0?如何在 VC++6.0 中模拟可变参数宏?
【发布时间】:2014-07-14 05:40:01
【问题描述】:

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, ...)

有什么可以帮助我的宏技巧吗?还是我最好使用显式参数并习惯冗余?

【问题讨论】:

  • 天哪,你肯定是在错误的方向迁移。具体来说,您需要使用 VC++ 6 的原因是什么?也许它可以在仍然使用现代编译器的同时解决?
  • @CodyGray。我的教授喜欢 VC++6.0。他认为它轻巧小巧,而 VS2010 显得过于笨重。所以我必须在提交时迁移我的代码。我会努力说服他的,但是他这个年纪的人容易固执。
  • 从命令行运行cl.exe 更加轻量和小巧。他根本不需要在 IDE 中打开您的代码!说真的,你的论点不应该是你更喜欢使用任何特定的开发环境。像大多数 C++ 开发人员一样,我也喜欢 VC++6 环境。问题以及您需要提出的论点是,它所捆绑的编译器实在太老了,无法教您有用的现代 C++ 实践。
  • @CodyGray。谢谢。这个论点更有说服力,我想和我的教授分享。无论如何,我仍然很好奇是否有可能在 VC++6 中解决这个问题。

标签: c visual-c++ c-preprocessor visual-c++-6 variadic-macros


【解决方案1】:
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)

这可能适用于您的情况。

【讨论】:

    【解决方案2】:

    您可以通过不使用它们来获得圆形可变参数。使用 ofstream 而不是 FILE*。像这样的

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

    假设您已经声明了一个名为 logfile 的 ofstream。对于简单的事情,您可以使用

    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++

    【讨论】:

      【解决方案3】:
      #define IND_FP Logger(indent)
      
      class Logger {
        public:
          Logger(int indent);
          int operator()(FILE* fp, char* format, ...);
        private:
          // an exercise for the reader
      };
      

      【讨论】:

      • 话虽如此,我不会在严肃的开发中推荐这个,就像我根本不会推荐任何宏一样。或者您的基于 printf 的日志记录样式。或者VC6。或者,从表面上看,你的教授。
      猜你喜欢
      • 2011-07-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-12
      • 1970-01-01
      • 1970-01-01
      • 2011-09-27
      • 2011-02-05
      相关资源
      最近更新 更多