我正在尝试根据模板类型专门化模板类的成员函数。特别是我想要基于多态类型的特化。我一直在为语法而苦苦挣扎。这是我的尝试,它显然会产生错误:doSomething()
class Base {};
class Derived : public Base {};
template<typename T>
class MyClass
{
public:
void doSomething();
};
template<>
template<typename T>
typename std::enable_if<std::is_base_of<Derived, T>::value>::type
void MyClass<T>::doSomething()
{
// Do something with Derived type
}
template<>
template<typename T>
typename std::enable_if<std::is_base_of<Base, T>::value &&
!std::is_base_of<Derived, T>::value>::type
void MyClass<T>::doSomething()
{
// So something with Base type
}
template<>
template<typename T>
typename std::enable_if<!std::is_base_of<Derived, T>::value>::type
void MyClass<T>::doSomething()
{
// Do something with all other types
}
编译给出..
error: two or more data types in declaration of 'doSomething'
顺便说一句,我确实编译了以下内容,但是特化在运行时没有按预期工作。基础类型和派生类型最终会通过 doSomething()
的非专用版本。
class Base {};
class Derived : public base {};
template<typename T>
class MyClass
{
public:
void doSomething()
{
// Do something for non-specialized types
}
};
template<>
void MyClass<Derived>::doSomething()
{
// Do something with Derived type
}
template<>
void MyClass<Base>::doSomething()
{
// So something with Base type
}
正确的语法是什么?
最佳答案
您不能仅仅因为 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 clean 解决方案:
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();
}
};
关于c++ - 如何根据模板类的基类专门化成员函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52901436/