for_stack for_stack - 1 month ago 4
C++ Question

Does it make any sense to specialize a function template with universal reference parameters?

For a template function, we can specialize it as follows:

template <typename T>
void func(T t) {}

// specialization for int
template <>
void func(int t) {}

However, I'm not sure how to specialize a template function with universal reference (a name from Meyers' book).

// template function with universal reference
template <typename T>
void func(T &&t) {}

I think simply replacing
doesn't make it a specialization:

template <>
void func(int &&t) {}

Since the template function can accept both lvalue and rvalue, while the 'specialized' one can only accept rvalue.

Should I also define a 'specialization' with lvalue reference?

// 'specialization' for lvalue reference
template <>
void func(int &t) {}

And the two 'specializations' make the specialization for the original template function? Or does it make any sense to have a specialization for it?


Specializing function templates is rarely a good idea. Very rarely. It looks like a mixture of template class specialization and overloading, but works like neither.

Functions have overloads. Use those.

If overloading does not get the exact behaviour you want, use a helper function with tag dispatching based overloading, or forward to a class.

In this case, it could be as simple as:

template <typename T>
void func(T&&){}
void func(int){}


template<class T>struct tag_t{};
template<class T>constexpr tag_t<T>tag{};
namepsace details{
  template <class T, class U>
  void func(tag_t<T>, U&&){}
  template <class U>
  void func(tag_t<int>, U&&){}
template <class T>
void func(T&&t){
  return details::func(tag<std::decay_t<T>>, std::forward<T>(t));