One way to do this is to use std::enable_if . This is the structure provided by the type_traits header. It is defined in such a way that enable_if<A,B>::type is type B if the logical condition A evaluates to true at compile time. Otherwise, it is empty.
Therefore, if you have a function template
template <typename T> void fun(T &&) { }
and you want to make sure that it is defined only if T is a specific type, you can use the enable_if<...>::type construct instead of the return type (here void ). The Boolean condition A then defined as something like: T is int , and type B is defined as the original return type of the function (here void ).
So, if we want fun be defined only if T is int , we get the following:
Note how a logical condition is defined as follows (excluding std:: for better readability):
is_same<int,typename decay<T>::type>::value
The decay operator is used to provide this, regardless of whether T int or int & (and a few other special cases).
Further notes: This trick is really only useful if the definition of the function in question is the same for both rvalue and lvalue. In many cases this is not the case (because the rvalue case will implement the move, the lvalue will not, or something like that).
A typical situation where both definitions are actually the same is when the body of the function is very short and does nothing but redirect the argument (s) to another (possibly overloaded) function call:
template <typename T> void fun(T &&obj) { other_fun(std::forward<T>(obj)); }
In this case, you probably should not use any enable_if or other trick, because declaring other_fun ensures that only certain types are ultimately accepted.