Search code examples
c++c++17constantsbind

must-non constant alias argument with its default argument constant


How do we code a must-non constant alias argument with its default argument must be constant as it's not being able to reference ?
and must be without overload function as its 91 lines long

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

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

//...
}

gcc gave

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

How to solve - with clear explanation - such this kind ?


Solution

  • The reason you get this error is, as you've discovered, that a non-const reference must bind to an lvalue: that is, it must bind to an object with a name. A temporary will not bind to a non-const reference: only to const Bar& or Bar&&, neither of which you want.

    That leaves us a couple of options.

    My personal favourite would be to not use default arguments at all, but instead provide an overload:

    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);
    }
    

    This is the easiest and most consistent option, in my opinion.

    Other possibilities include:

    • making a global whose sole purpose is to be a default argument (yuck, and interferes with multithreading):
      inline Bar default_bar;
      int fooBar(int board, Bar& bar = default_bar) {
        // ...
      }
      
    • using a pointer instead, with the caveat that you must check if they've provided an argument or not:
      int fooBar(int board, Bar* bar = nullptr) {
        // ..., but make sure to test bar!
      }
      
    • or otherwise using a std::optional<std::reference_wrapper<Bar>> or some-such type.