How to combine type constraints & implicit conversions with C++11 universal references?

231 views Asked by At

In a function I need to distinguish among lvalue and rvalue references, so the obvious path is to overload:

void myfunc(A&& a);
void myfunc(const A& a);

This has exactly the desired behaviour, with well defined type and implicit conversions. However there's too much code duplication and I'd prefer to encapsulate the relevant decisions inside, keeping only a single function, therefore passing by universal reference might be an option:

template <typename A>  void myfunc(A&& a);

However this has the unfortunate drawback that now any object can be passed as first parameter, so one might impose constraints via enable_if:

template <typename T, class  = typename enable_if<
    is_same<typename remove_const<typename    remove_reference<T>::type>::type, A>::value,
    T>::type>   
void myfunc( T&&  a);

This almost seems to do the job, but (I guess by templatizing already) we have lost a nice property of overloads which can trigger implicit conversion constructors to type A (say from type C parameters). Overloads are NOT an option since some functions might have 3 or more A&& parameters, no intention to deal with combinatorial explosion. Can implicit conversions be somehow recovered? Of course one workaround might be e.g. to add other allowed parameter types for A, and perform any needed conversion in the main function, but this is intrusive, ugly, explicits implicits and generates confusion (the original C parameter might be an lvalue [reference] and yet produce an rvalue by conversion). Any better way?

1

There are 1 answers

7
TartanLlama On

This is why std::is_convertible exists:

template <typename T, 
          class = typename enable_if<is_convertible<T, A>::value>::type>   
void myfunc( T&&  a);