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);
}
std::optional<std::string>("some string").value_or("c-string");
– Incroccitypename U = T
. No idea why that wasn't done. – Heretoforeopt.value_or(std::pair{1, 2});
– Transfuse