![](/img/trans.png)
[英]How do I specialize a static member of a template class on a templated type?
[英]How do I specialize member functions based on the base class of the templated class
我试图根据模板的类型来专门化模板类的成员函数。 我特别希望基于多态类型的专业化。 我一直在努力的语法。 这是我的尝试,它显然会产生错误: 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正常工作,必须在doSomething
模板参数而不是MyClass
参数上执行SFINAE检查。 最后,您的支票错了。
所以这是我的版本:
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();
}
};
另一个可能的解决方案是通过ForFoo
模板类,该模板类定义foo()
方法,并且对仅Base
类和Derived
类具有两个特殊化。 因此MyClass<T>
可以从ForFoo<T>
继承。
我的意思是...如果您按以下方式定义ForFoo
模板类集
template <typename T, typename = void>
struct ForFoo
{ void foo () { std::cout << "other type" << std::endl; } };
template <typename T>
struct ForFoo<T,
typename std::enable_if<std::is_base_of<Base, T>::value
&& ! std::is_base_of<Derived, T>::value>::type>
{ void foo () { std::cout << "Base type" << std::endl; } };
template <typename T>
struct ForFoo<T,
typename std::enable_if<std::is_base_of<Derived, T>::value>::type>
{ void foo () { std::cout << "Derived type" << std::endl; } };
MyClass
变成
template <typename T>
struct MyClass : public ForFoo<T>
{ };
以下是完整的C ++ 11示例
#include <iostream>
#include <type_traits>
class Base {};
class Derived : public Base {};
class A : Base {};
class B : Derived {};
class X {};
template <typename T, typename = void>
struct ForFoo
{ void foo () { std::cout << "other type" << std::endl; } };
template <typename T>
struct ForFoo<T,
typename std::enable_if<std::is_base_of<Base, T>::value
&& ! std::is_base_of<Derived, T>::value>::type>
{ void foo () { std::cout << "Base type" << std::endl; } };
template <typename T>
struct ForFoo<T,
typename std::enable_if<std::is_base_of<Derived, T>::value>::type>
{ void foo () { std::cout << "Derived type" << std::endl; } };
template <typename T>
struct MyClass : public ForFoo<T>
{ };
int main ()
{
MyClass<Base>{}.foo(); // Base
MyClass<Derived>{}.foo(); // Derived
MyClass<A>{}.foo(); // Base
MyClass<B>{}.foo(); // Derived
MyClass<X>{}.foo(); // other
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.