Вы не можете специализироваться doSomething
просто потому, что это не шаблон.MyClass
- это шаблон, и вы можете специализировать класс, каждая специализация имеет один doSomething
.Если это не то, что вам нужно, вам нужно сделать перегрузки шаблона doSomething
и, чтобы SFINAE работал, проверка SFINAE должна быть выполнена для параметра шаблона doSomething
, а не для параметра MyClass
.Наконец, ваши проверки неверны.
Так вот моя версия:
template<class T> struct MyClass
{
template <class U = T>
auto foo() -> std::enable_if_t<std::is_base_of_v<Base, U>
&& !std::is_base_of_v<Derived, U>>
{
foo_base();
}
template <class U = T>
auto foo() -> std::enable_if_t<std::is_base_of_v<Derived, U>>
{
foo_derived();
}
template <class U = T>
auto foo() -> std::enable_if_t<!std::is_base_of_v<Base, U>>
{
foo_else();
}
};
А вот батарея тестов:
class Base {};
class Derived : public Base {};
class A : Base {};
class B : Derived {};
class X {};
auto test()
{
MyClass<Base>{}.foo(); // foo_base
MyClass<Derived>{}.foo(); // foo_derived
MyClass<A>{}.foo(); // foo_base
MyClass<B>{}.foo(); // foo_derived
MyClass<X>{}.foo(); // foo_else
}
И, конечно,Я должен упомянуть чистое решение C ++ 17:
template<class T> struct MyClass
{
auto foo()
{
if constexpr (std::is_base_of_v<Derived, T>)
foo_derived();
else if constexpr (std::is_base_of_v<Base, T>)
foo_base();
else
foo_else();
}
};