Причина, по которой вы получаете эту ошибку, заключается в том, что, как вы обнаружили, ссылка не const
должна привязываться к lvalue: то есть она должна привязываться к объекту с именем. Временный не будет привязан к ссылке не-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>>
или какой-то подобный тип.