On cppreference, we can see std::optional takes a default value of U&& rather than T&&.
It makes me incapable of writing the following code:
std::optional<std::pair<int, int>> opt;
opt.value_or({1, 2}); // does not compile
opt.value_or(std::make_pair(1, 2)); // compiles
However, I find there is no benefit to using U&&, since U must be convertible to T here.
So, consider the following code, if we have some type U which differs from T, then there will be no perfect match. However, by performing an implicit cast, we can still resolve our call:
template< class U >
constexpr T value_or( T&& default_value ) const&;
I have the following code to test if a template function can take an argument which needs an extra implicit casting to make a perfect match, and it compiles:
#include <cstdio>
#include <optional>
#include <map>
struct A {
int i = 1;
};
struct B {
operator A() const {
return A{2};
}
};
template <typename T>
struct C {
void f(T && x) {
printf("%d\n", x.i);
}
};
int main() {
auto b = B();
C<A> c;
c.f(b);
}
I find there it no benefit by using U&&, since U must be convertible to T here.
U must be convertible to T, but a conversion can be expensive. Taking a forwarding reference (U&&) avoids performing that conversion if the argument is not used (if the object contains a value).
The same cppreference page says value_or is equivalent to:
bool(*this) ? **this : static_cast<T>(std::forward<U>(default_value)).
Here, static_cast<T> performs the conversion, but it is only performed if bool(*this) is false.
It is to allow perfect forwarding. If the signature were
constexpr T value_or( T&& default_value ) const&;
then T is not something that will be deduced, it is known from the class instantiation, meaning T&& default_value is just a plain rvalue reference to whatever T is.
By using
template< class U >
constexpr T value_or( U&& default_value ) const&;
The U needs to be deduced making it a forwarding reference.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With