Можно ли использовать std :: enable_if для выбора специализации шаблона члена?

Учитывая объявление класса

class A {
template <typename T> T foo();
};

Я хотел бы специализироваться A::foo для разных типов (int, …) и классы типов (POD, не POD) из T, К сожалению, я не могу использовать std::enable_if для последнего. Следующее не компилируется:

template <> int A::foo<int>(); // OK

template <typename T>
typename std::enable_if<is_pod<T>::value, T>::type foo(); // <<<< NOT OK!

template <typename T>
typename std::enable_if<!is_pod<T>::value, T>::type foo(); // <<<< NOT OK!

Проблема, вероятно, связана с std::enable_if<...> материал, являющийся частью сигнатуры функции, и что я не объявлял ни одного такого члена внутри A, Итак, как я могу специализировать элемент шаблона на основе характеристик типа?

8

Решение

Я не вижу смысла специализироваться здесь, мне кажется, что перегрузки функции вполне достаточно.

struct A
{
template <typename T>
typename std::enable_if<std::is_integral<T>::value, T>::type foo()
{
std::cout << "integral" << std::endl;
return T();
}

template <typename T>
typename std::enable_if<!std::is_integral<T>::value, T>::type foo()
{
std::cout << "not integral" << std::endl;
return T();
}
}

При проверке POD или отсутствия POD у вас есть только эти два варианта, поэтому более общая функция не нужна (и не допускается, потому что она будет неоднозначной). Вам нужно больше, чем это? Вы можете проверить явные типы без специализации с помощью std::enable_if<std::is_same<int, T>::value, T>::type,

4

Другие решения

Я просто перешлю это в структуру, которая хорошо справляется с этим:

#include <type_traits>
#include <iostream>

template <typename T, typename = void>
struct FooCaller;

class A {
public:
template <typename T>
T foo() {
// Forward the call to a structure, let the structure choose
//  the specialization.
return FooCaller<T>::call(*this);
}
};

// Specialize for PODs.
template <typename T>
struct FooCaller<T, typename std::enable_if<std::is_pod<T>::value>::type> {
static T call(A& self) {
std::cout << "pod." << std::endl;
return T();
}
};

// Specialize for non-PODs.
template <typename T>
struct FooCaller<T, typename std::enable_if<!std::is_pod<T>::value>::type> {
static T call(A& self) {
std::cout << "non-pod." << std::endl;
return T();
}
};

// Specialize for 'int'.
template <>
struct FooCaller<int> {
static int call(A& self) {
std::cout << "int." << std::endl;
return 0;
}
};
4

По вопросам рекламы [email protected]