Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

unifying const T& and T&& overloads

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?

like image 775
fredoverflow Avatar asked Apr 18 '12 14:04

fredoverflow


2 Answers

I'm not familiar with your optional, but perhaps you need to add:

typename remove_const< ... >::type

around your remove_reference in two places. (because your 1st overload of your 2-overload solution - which I assume is passing all of your tests - effectively does a remove_const when declaring optional<T>).

like image 65
Howard Hinnant Avatar answered Sep 24 '22 13:09

Howard Hinnant


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:

template<typename T>
optional<T> some(T x)
{
    return optional<T>(std::move(x));
}

If the caller calls it with a temporary or uses std::move on 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.

like image 32
Nicol Bolas Avatar answered Sep 24 '22 13:09

Nicol Bolas