如何将模板参数限制为模板化接口的专门化的后代
How to limit template parameters to a descendent that is a specialization of a templated interface?
假设如下情况:
- 有一个模板接口,定义了一组不同数据类型的操作。
- 该接口由定义实际数据类型操作的各种专用类实现。
- 有一些管理类必须工作2中定义的类的实例。
简化后的示例代码如下所示:
#include <iostream>
#include <type_traits>
template <typename R, typename S>
class ICanDoIt
{
public:
virtual void doStuff() = 0;
protected:
ICanDoIt<R, S>(R rA, S sA) : r(rA), s(sA) {};
R r;
S s;
};
class DoesIt : public ICanDoIt<int, double>
{
public:
DoesIt(int iA, double dA) : ICanDoIt(iA, dA) {};
virtual void doStuff()
{ std::cout << "r * s = " << r * s << " done." << std::endl; }
};
template <typename T>
class NeedsSomeoneWhoCanDoIt
{
static_assert(std::is_base_of<ICanDoIt<R, S>, T>::value,
"T needs to be able to do it.");
public:
NeedsSomeoneWhoCanDoIt(const T& doesItA) : doesIt(doesItA) {};
void getItDone() { doesIt.doStuff(); };
private:
T doesIt;
};
int main()
{
DoesIt doesIt(5, 2.2);
NeedsSomeoneWhoCanDoIt<DoesIt> needsIt(doesIt);
needsIt.getItDone();
}
如果你解模板接口"ICanDoIt"代码将实际工作。但是模板化版本的static_assert将失败,因为ICanDoIt的模板参数被封装并隐藏在DoesIt声明中执行的特化中。
如何将管理类(NeedsSomeoneWhoCanDoIt)模板参数"T"限制为 ICanDoIt的任何专门化,而不管在ICanDoIt专门化期间为R, S选择了哪种类型?
您始终可以使用于实例化ICanDoIt
的R
和S
的实际类型对派生类可访问,即
template <typename R, typename S> class ICanDoIt {
public:
typedef R R_t;
typedef S S_t;
virtual void doStuff() = 0;
};
使你的static_assert
变成
static_assert(std::is_base_of<ICanDoIt<typename T::R_t, typename T::S_t>,
T>::value,
"T needs to be able to do it.");
根据你的实际代码看起来像设计可能会变得更清晰,如果你定义一个纯抽象的基类(即一个实际类型ICanDoItBase
而不是一个模板),你会继承ICanDoIt
目前模板化的功能,这将再次成为DoesIt
的基础。
NeedsSomeoneWhoCanDoIt
可以直接使用多态基类ICanDoItBase
,而不需要任何额外的类型检查。
您不需要发布模板参数。标准的基于sfinae的方法可以很好地工作。
namespace detail {
template<class R, class S>
std::true_type test(ICanDoIt<R, S>*);
std::false_type test(...);
}
template<class T>
using can_do_it = decltype(detail::test((T*)nullptr));
相关文章:
- C++核心准则 C35 对于接口类"A base class destructor should be either public and virtual, or protected and nonv
- Visual C++GC接口如何启用它以及要包含哪个库
- Windows.h与GLFW.h的接口
- 当字段可以为null时,如何使用C++接口在Avro中写入数据
- 提供与TMP和SFINAE的通用接口
- 为重写std::exception的库生成swig接口时出错
- 内联如何影响模块接口中的成员函数
- COM 接口 c# 封送数组数组
- 如何在 SCIP C++ 接口中获取 MILP 约束矩阵中的系数值
- 重载 -> shared_ptr 个实例中的箭头运算符<interface>,接口中没有纯虚拟析构函数
- 如何绑定 C++ gRPC 客户端的网络接口
- 模板化接口 - 创建一个泛型模板类以返回任何容器
- 如何从实现接口的模板化类实例访问结构
- 带有进度表的 curl 多接口程序
- 设计帮助 - 为不同类型的消息处理通用接口的设计模式
- 我可以在具有一个标头和一个接口的 cpp 文件中有多个嵌入吗?
- 类接口,可以创建N个方法
- 类具有相同的接口,但参数的类型不同
- 如何与 Cheerp/js 中的 extern 变量接口?
- 如何将模板参数限制为模板化接口的专门化的后代