must-non constant 别名参数及其默认参数常量

must-non constant alias argument with its default argument constant

我们如何编写一个 must-non constant 别名参数,其默认参数 must be constant 因为它不能引用?
并且必须没有重载功能,因为它的 91 行长

Bar {
  int on;
  Bar(){};
  Bar(bool o): off{o}{}
  bool off; 
}

int fooBar(int board, Bar& bar = static_cast<Bar>(1)) {

//...
}

gcc 给了

error: cannot bind non-const lvalue reference of type 'Bar&' to an rvalue of type 'Bar'

如何解决 - 有明确的解释 - 这种?

如您所见,出现此错误的原因是非 const 引用必须绑定到左值:也就是说,它必须绑定到具有名称的对象。临时文件不会绑定到非 const 引用:仅绑定到 const Bar&Bar&&,两者都不想要。

这给我们留下了几个选择。

我个人最喜欢的是根本不使用默认参数,而是提供重载:

int fooBar(int board, Bar& bar) {
  // ...
}

int fooBar(int board) {
  // to save code duplication you can call in fooBar
  Bar b{1};
  return fooBar(board, b);
}

在我看来,这是最简单、最一致的选择。

其他可能性包括:

  • 创建一个全局变量,其唯一目的是作为默认参数(糟糕,并且会干扰多线程):
    inline Bar default_bar;
    int fooBar(int board, Bar& bar = default_bar) {
      // ...
    }
    
  • 改为使用指针,但需要注意的是您必须检查它们是否提供了参数:
    int fooBar(int board, Bar* bar = nullptr) {
      // ..., but make sure to test bar!
    }
    
  • 或以其他方式使用 std::optional<std::reference_wrapper<Bar>> 或类似的类型。

你可以定义这样的辅助函数:

template <typename Ty> Ty &make_ref(const Ty &cref)
{
    return const_cast<Ty&>(cref);
}

然后使用如下:

int fooBar(int board, Bar& bar = make_ref(Bar(1))) {
//...
}