I have the following two function template overloads:
template<typename T>
optional<T> some(const T& x)
{
return optional<T>(x);
}
template<typename T>
typename std::enable_if<std::is_rvalue_reference<T&&>::value, optional<T> >::type
some(T&& x)
{
return optional<T>(std::move(x));
}
My first attempt at unifying the overloads via perfect forwarding failed:
template<typename T>
optional<T> some(T&& x)
{
return optional<T>(std::forward<T>(x));
}
error: forming pointer to reference type 'const std::basic_string<char>&'
As did my second attempt:
template<typename T>
optional<typename std::remove_reference<T>::type> some(T&& x)
{
return optional<typename std::remove_reference<T>::type>(std::forward<T>(x));
}
error: no matching function for call to
'std::basic_string<char>::basic_string(gpa::optional<const std::basic_string<char> >)'
Is there a clean way to unify the overloads, or should I just live with having them?
In general, the best way to do this is to take the object by value and let the caller decide whether to copy or move it:
If the caller calls it with a temporary or uses
std::moveon their value, then it’s moved. Otherwise it’s copied.Yes, this does mean that you’ll do one additional move (which, if movement is the same as copying, means doing two copies). If that’s a significant performance problem for you, then you’ll have to use the two overloads implementation.