【问题标题】:Can I Conditionally Use More Than 1 Argument?我可以有条件地使用多个参数吗?
【发布时间】:2017-12-18 16:47:46
【问题描述】:

所以这段代码作为一个例子很好用:

#ifdef DEBUG
#define DECLARE_DEBUG_PARAM(x) x
#define PASS_DEBUG_PARAM(x) x
#else
#define DECLARE_DEBUG_PARAM(x) void
#define PASS_DEBUG_PARAM(x)
#endif

int foo(DECLARE_DEBUG_PARAM(const bool param)) {
#ifdef DEBUG
    if(param) {
        cout << "DEBUG true\n";
    } else {
        cout << "DEBUG false\n";
    }
#else
    cout << "RETAIL\n";
#endif
}

int main() {
    foo(PASS_DEBUG_PARAM(true));
}

Live Example

但我想将它用于第二个参数,例如:int foo(const int param1, DECLARE_DEBUG_PARAM(const int param2)) 显然这不适用于我当前的DECLARE_DEBUG_PARAM 定义,我收到错误:

错误:在参数声明中无效使用类型void

是否有一些我可以使用的 noop 参数类型允许这样做?

【问题讨论】:

    标签: c++ parameters macros parameter-passing precompile


    【解决方案1】:

    您应该在宏中包含逗号并且不要发出 void。

    #ifdef DEBUG
    #define DECLARE_DEBUG_PARAM(x) , x
    #else
    #define DECLARE_DEBUG_PARAM(x)
    #endif
    int foo(const int param1 DECLARE_DEBUG_PARAM(const int param2))
    

    或者在参数中包含逗号,所以这个宏可以在任何地方使用:

    #ifdef DEBUG
    #define DECLARE_DEBUG_PARAM(...) __VA_ARGS__
    #define PASS_DEBUG_PARAM(...) __VA_ARGS__
    #else
    #define DECLARE_DEBUG_PARAM(...)
    #define PASS_DEBUG_PARAM(...)
    #endif
    
    int foo1(DECLARE_DEBUG_PARAM(const bool param)) {
    #ifdef DEBUG
        if(param) {
            cout << "DEBUG true\n";
        } else {
            cout << "DEBUG false\n";
        }
    #else
        cout << "RETAIL\n";
    #endif
    }
    
    int foo2(int DECLARE_DEBUG_PARAM(, const bool param)) {
    #ifdef DEBUG
        if(param) {
            cout << "DEBUG true\n";
        } else {
            cout << "DEBUG false\n";
        }
    #else
        cout << "RETAIL\n";
    #endif
    }
    
    int main() {
    
        foo1(PASS_DEBUG_PARAM(true));
        foo2(0 PASS_DEBUG_PARAM(,true));
    
        return 0;
    }
    

    Working code online.

    【讨论】:

    • 是的,看起来在内部处理逗号的东西将是唯一的方法。但我不认为这是一个彻底的解决方案,因为如果它是唯一的参数怎么办。我可能不得不要求用户在必要时在内部传递逗号。
    • 使用__VA_ARGS__,你可以写int foo(const int param1 DECLARE_DEBUG_PARAM(, int param2))来处理foo,参数为0或n。
    【解决方案2】:

    我会建议一些不同的选择。


    1) 使用默认值:

    enum class DebugSwitch {No_debug, Debug}
    
    void function(int param1, DebugSwitch debug_param = DebugSwitch::No_debug)
    {...}
    

    2) 使用参数对象

    struct Parameters
    {
         int param1;
         bool debug_param;
         // ....
    };
    
    void function(Parameter& p)
    {
         ///...
    }
    

    为什么?您正在增加可以发送到函数的值的可能组合数量;

    DEBUG defined + param == true
    DEBUG defined + param == false
    DEBUG not defined + param == true
    DEBUG not defined + param == false
    

    为确保您正确处理所有组合 - 减少“转向”变量的数量。

    【讨论】:

      【解决方案3】:

      引用 C++ 常见问题解答:

      因为#define 宏在 4 种不同的方面是邪恶的:evil#1evil#2evil#3evil#4。有时你无论如何都应该使用它们,但它们仍然是邪恶的。

      在这里使用宏没有意义。这只是#ifdef 输出代码,但需要用户查找。一个更好的方法就是使用#ifdef:

      int foo(
      #ifdef DEBUG
              const bool param
      #endif
             );
      int foo(const int param1
      #ifdef DEBUG
              , const int param2
      #endif
             );
      

      调用做同样的事情:

      foo(
      #ifdef DEBUG
          true
      #endif
         );
      foo(13
      #ifdef DEBUG
          , 42
      #endif
         );
      

      对于采用少量参数的函数来说,这段代码可能有点混乱,如果认为这样更易读,可以使用#else 进行布局:

      #ifdef DEBUG
          int foo(const bool param);
      #else
          int foo();
      #endif
      #ifdef DEBUG
          int foo(const int param1, const int param2);
      #else
          int foo(const int param1);
      #endif
      

      可以对调用执行相同的操作:

      #ifdef DEBUG
          foo(true);
      #else
          foo();
      #endif
      #ifdef DEBUG
          foo(13, 42);
      #else
          foo(13);
      #endif
      

      【讨论】:

        猜你喜欢
        • 2018-09-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-12-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多