Unification of const T & & T && overload

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 combining overloads via flawless 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>&' 

Like 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 overloads, or should I just live with them?

+6
source share
2 answers

In general, the best way to do this is to take an 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 temporary or uses std::move by their value, it moves. Otherwise, it will be copied.

Yes, that means that you take one more step (which, if the movement is the same as copying, means making two copies). If a significant performance issue is important to you, you will have to use the implementation of two overloads.

+1
source

I am not familiar with your optional , but maybe you need to add:

 typename remove_const< ... >::type 

around your remove_reference in two places. (because your first overload of your 2-overload solution, which I believe passes all your tests, effectively remove_const when declaring optional<T> ).

+4
source

Source: https://habr.com/ru/post/913545/


All Articles