I'm currently playing around with some of the new C++17 features, specifically std::optional
, and I decided I'd have a go at coming up with a minimum-finding function using variadic template templates. This is what I have so far:
template <template <typename> typename Opt,
typename T>
Opt<T> optional_min(Opt<T>&& opt) {
return std::forward<Opt<T>>(opt);
}
template <template <typename> typename Opt0,
template <typename> typename Opt1,
template <typename> typename... Opts, typename T >
std::common_type_t<Opt0<T>, Opt1<T>, Opts<T>...>
optional_min(Opt0<T>&& opt0, Opt1<T>&& opt1, Opts<T>&&... opts) {
if (!opt0 && !opt1)
{
return optional_min(std::optional<T>(std::nullopt), std::forward<Opts<T>>(opts)...);
}
else if (opt0 && !opt1)
{
return optional_min(opt0, std::forward<Opts<T>>(opts)...);
}
else if (!opt0 && opt1)
{
return optional_min(opt1, std::forward<Opts<T>>(opts)...);
}
else
{
return (*opt0 < *opt1) ?
optional_min(opt0, std::forward<Opts<T>>(opts)...)
: optional_min(opt1, std::forward<Opts<T>>(opts)...);
}
}
int main() {
std::optional<int> a = 9;
std::optional<int> b = std::nullopt;
std::optional<int> c = 4;
if (auto x = optional_min(a, b, c))
std::cout << *x << std::endl;
return 0;
}
It seems like my forwarding isn't working. I'm still new to the idea of forwarding, so I could just be missing something silly. The error I get is this:
error: no matching function for call to 'optional_min(std::optional<int>&, std::optional<int>&, std::optional<int>&)'
error: cannot bind rvalue reference of type 'std::optional<int>&' to lvalue of type 'std::optional<int>'
auto x = optional_min(a, b, c);
My compiler is also telling me that my variadic optional_min
function is only a close match, and that it's trying to match my other optional_min
function, that one that only takes in one argument. Does anyone know why this might be the case? Please let me know if you need to know a little more.
None of optional_min
's parameters are forwarding references. They are all rvalue references.
Forwarding references are formed when you declare a parameter to be an rvalue reference to a deduced template type parameter, but that's not the case here. optional_min
's parameters are rvalue references to instantiations of deduced template template parameters.
To avoid this, just get rid of the Opt0
, Opt1
and Opts
template template parameters, and use type parameters directly:
template <typename Opt0, typename Opt1, typename... Opts>
auto optional_min(Opt0&& opt0, Opt1&& opt1, Opts&&... opts) {
//...
}
You could use SFINAE to limit the type parameters to instantiations of std::optional
if that's your goal.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.