I'm trying to write syntactic sugar, in a monad-style, over std::optional
. Please consider:
template<class T>
void f(std::optional<T>)
{}
As is, this function cannot be called with a non-optional T
1 (e.g. an int
), even though there exists a conversion from T
to std::optional<T>
2.
Is there a way to make f
accept an std::optional<T>
or a T
(converted to an optional at the caller site), without defining an overload3?
1) f(0)
: error: no matching function for call to 'f(int)'
and note: template argument deduction/substitution failed
, (demo).
2) Because template argument deduction doesn't consider conversions.
3) Overloading is an acceptable solution for a unary function, but starts to be an annoyance when you have binary functions like operator+(optional, optional)
, and is a pain for ternary, 4-ary, etc. functions.
Another version. This one doesn't involve anything:
template <typename T>
void f(T&& t) {
std::optional opt = std::forward<T>(t);
}
Class template argument deduction already does the right thing here. If t
is an optional
, the copy deduction candidate will be preferred and we get the same type back. Otherwise, we wrap it.