Reputation: 25663
I play around with template specialization and SFINAE.
As for the following example, the things seems easy:
template <class T>
void Do(T t, typename std::enable_if<std::is_integral<T>::value >::type* = 0)
{
cout << "is integer" << endl;
}
template <class T>
void Do(T t, typename std::enable_if<std::is_floating_point<T>::value >::type* = 0)
{
cout << "is float" << endl;
}
No I tried std::is_array, but the specialization with std::is_array is never used.
So I tried out why is_array never matches:
template <int num>
void Do( int a[num])
{
cout << "int array size " << num << endl;
}
void Do( int* x)
{
cout << "int*" << endl;
}
...
int e[] = { 1,2,3 };
Do(e);
...
The first mystery for me is, that the specialization with "int a[num]" did never catch! The function parameter always has the type int*.
If I use reference types I got the "correct" result:
template <int num>
void Do( int (&a)[num])
{
cout << "int array size " << num << endl;
}
void Do( int* &x)
{
cout << "int*" << endl;
}
So my question comes up: Is there a reasonable usage of std::is_array in combination with template function parameters? I know that
cout << boolalpha << std::is_array<decltype(e)>::value << endl;
will give me the correct result. But declaring the template selection manually gives me no functional add on. I there any way to detect (with or without SFINAE) that an template specialization from function parameters fits to an array?
Upvotes: 2
Views: 2825
Reputation: 47770
I think you got it yourself - pass arrays to template functions by reference, if you want to use their type in the secialization.
The reason you want to do this is array-to-pointer decay, which is one of the few implicit conversions that happen to template function arguments before they are matched to the parameter types. That's why T
was a pointer when you tried to check that it is an array type in DoIt
. However, array-to-pointer decay does not happen when the target type is reference type. So, to sum up:
template <class T>
void Do(T& t, typename std::enable_if<std::is_array<T>::value >::type* = 0)
should work.
BTW the boring way of not using SFINAE
template <class T, unsigned N>
void Do(T (&t)[N])
works too.
Upvotes: 5