С++ 11: Специализация функции шаблона для типов Integer
Предположим, что у меня есть функция шаблона:
template<typename T>
void f(T t)
{
...
}
и я хочу написать специализацию для всех примитивных целочисленных типов. Каков наилучший способ сделать это?
Что я имею в виду:
template<typename I where is_integral<I>::value is true>
void f(I i)
{
...
}
и компилятор выбирает вторую версию для целых типов, а первую версию для всего остального?
Ответы
Ответ 1
Используйте SFINAE
// For all types except integral types:
template<typename T>
typename std::enable_if<!std::is_integral<T>::value>::type f(T t)
{
// ...
}
// For integral types only:
template<typename T>
typename std::enable_if<std::is_integral<T>::value>::type f(T t)
{
// ...
}
Обратите внимание, что вам нужно будет включить полное возвращаемое значение std::enable_if
даже для объявления.
Ответ 2
Я бы использовал разрешение перегрузки. Это избавляет вас от необходимости использовать валовой SFINAE-хак. К сожалению, есть много областей, где вы не можете избежать этого, но, к счастью, это не один из них.
template<typename T>
void f(T t)
{
f(t, std::is_integral<T>());
}
template<typename T>
void f(T t, std::true_type)
{
// ...
}
template<typename T>
void f(T t, std::false_type)
{
// ...
}
Ответ 3
Используя С++ 11, можно использовать std:: enable_if (http://en.cppreference.com/w/cpp/types/enable_if):
template<typename T, class = typename std::enable_if<std::is_integral<T>::value>::type>
void f(T t) {...}
Ответ 4
Вы можете использовать вспомогательный шаблон, который вы можете специализировать следующим образом:
#include <string>
#include <iostream>
#include <type_traits>
template <typename T, bool = std::is_integral<T>::value>
struct Foo {
static void bar(const T& t) { std::cout << "generic: " << t << "\n"; }
};
template <typename T>
struct Foo<T, true> {
static void bar(const T& t) { std::cout << "integral: " << t << "\n"; }
};
template <typename T>
static void bar(const T& t) {
return Foo<T>::bar(t);
}
int main() {
std::string s = "string";
bar(s);
int i = 42;
bar(i);
return 0;
}
выход:
generic: string
integral: 42