Do not provide overloads for every possible type you want to use. This breaks the logic of using generic code in the first place. That been said, the need to provide a specialization for every type maybe points out that this was not the most successfull application of templates, not to mention that messing around with function template specialization is not the prettiest choice as Sutter says
Since you need a logic separation between mutually exclusive types (built ins and non built ins) here's an alternative :
template<class T>
typename std::enable_if< std::is_fundamental<T>::value >::type foo_func(T arg)
{
std::cout << "Call for built in types" << std::endl;
}
template<class T>
typename std::enable_if< !std::is_fundamental<T>::value >::type foo_func(T const &arg)
{
std::cout << "Call for non built in types" << std::endl;
}
To explain the code here what happens:
1) std::is_fundamental will return false or true at compile time depending on whether T is user defined or a built in type respectively.
2) std::enable_if will "allow" the declaration of the function template for true in the first case and false in the second, so no resolution problems can happen.
3) so when calling foo_func for built in types, the first version will be used and T (int, float and so on) is passed by value (which is faster for built ins) and ... well you can imaging what happens in the other case.