【问题标题】:C++ default arguments out of order?C ++默认参数乱序?
【发布时间】:2018-05-15 19:38:16
【问题描述】:

假设我有:

void f(bool option1 = false, bool option2 =false, bool option3 = false) 
{
     ... 
}

我想打电话:

f(option2=true);

这在 C++ 中可行吗?

【问题讨论】:

  • 如果您来自 Python 背景,那么您的期望是错误的。 C++ 基于 C,这是不可能的。
  • 不,您只能通过明确指定两个参数来进行调用。不过,您真的需要第一个参数作为默认值吗?也许是为了重构,但似乎想得太远了。
  • 简短回答:否
  • 你可以考虑Named Parameter Idiom
  • 我并不反对,你可以在这里看到许多聪明的 C++ 主义的例子,它们让你得到你想要的东西,但是以 C++ 的方式。我从不争辩 C++ 是完美的,它有很多 的怪癖和问题,他们仍在努力解决,但我要说的是,如果没有好的参考,C++ 不是你可以完全吸收的东西.这远非直观,无辜的错误会导致各种非常糟糕的未定义行为。知道你在处理什么,做好准备。只是在这里寻找你。

标签: c++


【解决方案1】:

无法按照您在 C++ 中建议的方式调用函数。您可以通过元编程模拟命名参数,或者简单地将struct 传递给您的函数。例如

struct options
{
    bool option0{false};
    bool option1{false};
    bool option2{false};
}; 

void f(options opts = {});

C++11 用法:

options opts;
opts.option2 = true;
f(opts);

C++2a 用法:

f({.option2=true});

【讨论】:

  • 使用 C++20,如果你眯着眼睛,它甚至看起来像命名参数:f({.option2 = true})
  • @Justin:领先我几秒钟,正在编辑:)
【解决方案2】:

作为替代方案,您可以使用位标志:

enum FOption
{
    option0 = 1 << 0,
    option1 = 1 << 1,
    option2 = 1 << 2,
};

void f(FOption opt = 0) {
    const bool opt0 = opt & option0;
    const bool opt1 = opt & option1;
    const bool opt2 = opt & option2;
    /*...*/
}

然后像这样使用它:

f(option2);
f(option1 | option2);

【讨论】:

    【解决方案3】:

    我有 12 个可选参数

    如果您所有的可选参数都是bool 类型,您可以使用flag enum

    enum class OptionFlags {
        Option1 = 1,
        Option2 = 2,
        Option3 = 4,
        Option4 = 8
    };
    
    inline OptionFlags operator|(OptionFlags a, OptionFlags b) {
        return static_cast<OptionFlags>(static_cast<int>(a) | static_cast<int>(b));
    }
    

    现在您可以按如下方式定义您的函数:

    void f(OptionFlags f) {
        ...
    }
    

    哪些用户会这样称呼:

    f(OptionFlags::Option1 | OptionFlags::Option3); // Option1==true, Option3==true
    

    【讨论】:

      【解决方案4】:

      不,你不能这样做,参数的名称可以说在调用站点不存在。有几种方法可以解决这个问题。实际上,我已经说过,仅 3 个bool 参数就已经是积极做一些事情以避免给调用者造成混淆并允许用户拥有正确名称的原因。

      有些人可能不喜欢这种简单的方法,但它可以作为一个起点:

      struct f_params {
          bool a;
          bool b;
          bool c;
          f_params() : a(false),b(false),c(false) {}
          f_params& set_a(bool x) { 
              a = x;
              return *this;
          }
      };
      

      调用者现在可以只设置非默认值:

      f_params x;
      x.a = true;
      f(x);
      // or..
      f(f_params().set_a(true));
      

      【讨论】:

        猜你喜欢
        • 2010-12-01
        • 1970-01-01
        • 2011-12-28
        • 2012-05-04
        • 2011-09-25
        • 2011-05-07
        • 2012-05-06
        • 2015-05-09
        相关资源
        最近更新 更多