Я играю с шаблонной специализацией и SFINAE.
Что касается следующего примера, все выглядит просто:
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;
}
Нет, я пробовал std :: is_array, но специализация с std :: is_array никогда не используется.
Поэтому я попробовал, почему is_array никогда не совпадает:
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);
...
Первая загадка для мне в том, что специализация с «int a [num]» никогда не ловила! Параметр функции всегда имеет тип int *.
Если я использую ссылочные типы, я получаю «правильный» результат:
template <int num>
void Do( int (&a)[num])
{
cout << "int array size " << num << endl;
}
void Do( int* &x)
{
cout << "int*" << endl;
}
Поэтому у меня возникает вопрос: есть ли разумное использование std :: is_array в сочетании с параметрами функции шаблона? я знаю это
cout << boolalpha << std::is_array<decltype(e)>::value << endl;
даст мне правильный результат. Но объявление выбора шаблона вручную не дает мне функционального дополнения. Есть ли способ обнаружить (с или без SFINAE), что специализация шаблона из параметров функции соответствует массиву?
Я думаю, вы получили это сами — передайте массивы шаблонным функциям по ссылке, если вы хотите использовать их тип в секуляризации.
Причина, по которой вы хотите это сделать, — это затухание массива в указатель, которое является одним из немногих неявных преобразований, которые происходят с аргументами функции шаблона, прежде чем они будут сопоставлены с типами параметров. Вот почему T
был указатель, когда вы пытались проверить, что это тип массива в DoIt
, Однако распад массива на указатель делает не происходит, когда целевой тип является ссылочным типом. Итак, подведем итог:
template <class T>
void Do(T& t, typename std::enable_if<std::is_array<T>::value >::type* = 0)
должно сработать.
Кстати скучный способ не использовать SFINAE
template <class T, unsigned N>
void Do(T (&t)[N])
тоже работает
Других решений пока нет …