c++ - 如何根据模板类的基类专门化成员函数
问题描述
我正在尝试根据模板类型专门化模板类的成员函数。特别是我希望有基于多态类型的专业化。我一直在为语法苦苦挣扎。这是我的尝试,显然会产生错误:声明中的两种或多种数据类型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
模板参数而不是参数进行 SFINAE 检查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();
}
};
推荐阅读
- node.js - 如何知道是否存在一个名为“A”的顶点,其中包含数据?
- mongodb - 如何制作 sum(field)-sum(field2) 并获得所有文档的单个结果
- javascript - 如何检查是否在php中检查了span od xheckbox?
- c - 清除分配给C中字符串的内存?
- tfs - Azure devops 管道初始化作业失败并显示错误消息“#[error]bad content type”
- c# - Treeview - 在放置在 NodeMouseClick 事件上的消息弹出窗口上单击取消时无法恢复先前的选择
- php - 上传带有亚洲字符的 CSV 文件,特别是“泰语”返回 ??? 在上传的文件上
- c# - 如何在我的列表中存储每个单独的正则表达式匹配主题标签?
- c# - 纸、剪刀、石头如何显示正确的结果?
- hibernate - 什么可能导致 Spring/Hibernate 设置找不到实体 ID?