Это возможно, поскольку можно определить, является ли параметр шаблона массивом или нет:
template<class T> struct is_array {
enum { value = false };
};
template<class T, size_t N> struct is_array<T[N]> {
enum { value = true };
};
template<class T> void f(T const&) {
std::cout << is_array<T>::value << std::endl;
}
Сочетая это с enable_if
, вышеприведенное можно сделать однозначным. Например, используя Boost.TypeTraits:
template <typename T, size_t SZ>
typename boost::enable_if<boost::is_array<T>, void>::type
f(T (&arr)[SZ]) {}
С ссылками, однако, SFINAE вообще не требуется:
template<class T, size_t SZ> void f(T (&arr)[SZ]) {}
template<class T> void f(T* const& t) {}
Йоханнес предлагает еще одну опцию, которая лучше подходит к данной ситуации - вместо этого используется SFINAE для проблемной перегрузки указателя:
template <typename T, size_t SZ> void f(T (&arr)[SZ]) {}
template <typename T>
typename boost::enable_if<boost::is_pointer<T>, void>::type
f(T ptr) {}