代码之家  ›  专栏  ›  技术社区  ›  Zain Rizvi viperguynaz

如何通过#define函数向格式化字符串函数调用添加参数

  •  2
  • Zain Rizvi viperguynaz  · 技术社区  · 14 年前

    我想创建宏,将参数插入到函数调用中。例如,我有一个函数 Action() 声明如下。操作的输入是状态号的枚举和带可选参数的格式化字符串。

    Action( ActionState1, "someText %d", &arg) 具有 ActionState1 对于state参数,我可以调用 State1("someText %d", &arg) 行动状态1

    #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 回复  |  直到 9 年前
        1
  •  2
  •   Community CDub    8 年前

    我相信 __VA_ARGS__

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

    这是一个C99功能,并且 Wikipedia claims 它们不是任何官方C++标准的一部分(我注意到这是因为你使用C++标签),但这是一个相当流行的扩展。有一些很好的讨论 this question

        2
  •  2
  •   dirkgently    14 年前

    不,这不能用预处理器来完成。预处理器允许您将实体串起来,但不能反向操作。为了你想要的,你需要分手 State1 到两个组件 State 1 (后者更重要)继续通话。

    然而,更重要的问题是你为什么要这么做?这样的转换很难保存任何输入,也很难获得可读性。

    不过,您可以使用模板在附近获得一些信息:

    template <size_t N> 
    T State(string fmt, ...) { return Action(N, fmt, ...); } // assume T Action(size_t, ...);
    

    State<1>(fmtStr, ...);
    State<2>(fmtStr2, ...);
    

    不过,在我看来,这里几乎没有任何语法上的好处。

        3
  •  0
  •   Mark B    14 年前

    你为什么要创造这样的东西?在C++中,使用流式运算符或类似的方法来使用VARARGS,因为它在其他方面获得了类型安全。

    我不相信在C++预处理器宏中有什么方法可以实现你想要的。如果您有一个vau-list版本的Action,那么您可能可以通过以下方式逃脱惩罚,但是我似乎记得 ... 一定是吊舱-不幸的是,快速搜索无法确认或否认这一点。

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