C++ 有没有一种巧妙的方法可以避免重写在多重继承中使用的模板基类的所有纯虚拟函数
相当复杂(和糟糕)的标题,下面是我所说的示例:C++ 有没有一种巧妙的方法可以避免重写在多重继承中使用的模板基类的所有纯虚拟函数,c++,templates,inheritance,multiple-inheritance,member-functions,C++,Templates,Inheritance,Multiple Inheritance,Member Functions,相当复杂(和糟糕)的标题,下面是我所说的示例: struct type1 {}; struct type2 {}; struct type3 {}; template< typename TYPE > struct interface { virtual void f( TYPE ) = 0; }; struct processor { template< typename TYPE > void f( TYPE ) { //
struct type1 {};
struct type2 {};
struct type3 {};
template< typename TYPE >
struct interface {
virtual void f( TYPE ) = 0;
};
struct processor {
template< typename TYPE >
void f( TYPE ) {
// something + for some TYPE-s have specializations, but it's irrelevant
}
};
struct der: interface< type1 >, interface< type2 >, interface< type3 > {
processor p;
void f( type1 t ){ p.f( t ); }
void f( type2 t ){ p.f( t ); }
void f( type3 t ){ p.f( t ); }
};
struct type1{};
结构类型2{};
结构类型3{};
模板<类型名称类型>
结构接口{
虚空f(TYPE)=0;
};
结构处理器{
模板<类型名称类型>
空f(类型){
//对于某些类型的s,something+有专门化,但它是不相关的
}
};
结构顺序:接口,接口,接口{
处理器p;
空f(type1t){p.f(t);}
空f(type2t){p.f(t);}
空f(type3t){p.f(t);}
};
在der
中是否有任何巧妙的方法来避免所有覆盖?在实际情况中,der
继承接口
10次(使用不同的模板类型,将来可以扩展)。当他们的身体是一样的时候,有10+的f
覆盖是相当丑陋的
processor
可以更改为任何内容,而且der::p
可以是一些容器,其中包含一个模板
-dprocessor
,等等
听起来我想要一个虚拟模板
成员函数f
,这是不允许的
我考虑过使用宏,但我不喜欢这个想法
编辑注意:很遗憾,无法使用c++11。并且无法更改不在层次结构中的
typeN
类型。您可以将der
作为模板:
template <typename ...> struct der;
template <> struct der<>
{
processor p;
};
template <typename Base, typename ...Rest>
struct der<Base, Rest...> : der<Rest...>, interface<Base>
{
void f(Base x) { this->p.f(x); }
};
模板结构;
模板结构
{
处理器p;
};
模板
结构der:der,接口
{
void f(Base x){this->p.f(x);}
};
然后使用:
der<type1, type2, type3> d;
derd;
以下是使用CRTP的替代设计:
template <typename Actual, typename Base> struct FImpl : Base
{
void f(Base x) { static_cast<Actual*>(this)->p.f(x); }
};
template <typename ...T> struct der : FImpl<der, T>...
{
processor p;
};
模板结构FImpl:Base
{
void f(Base x){static_cast(this)->p.f(x);}
};
模板结构顺序:FImpl。。。
{
处理器p;
};
C++03解决方案
(有关使用C++11功能的解决方案,请参见KerrekSB的答案)
您可以使用另一层继承和CRTP将调用分派到处理器:
template< typename TYPE, class ProcessorHolder >
struct processorDispatch : interface<TYPE> {
virtual void f( TYPE t ) override {
processor& p = static_cast<ProcessorHolder*>(this)->p; //CRTP --> explicit downcast
p.f(t);
}
};
模板
结构processorDispatch:接口{
虚空f(t型)覆盖{
处理器&p=static_cast(this)->p;//CRTP-->显式下行
p、 f(t);
}
};
并将其用作
struct der: processorDispatch< type1,der >, processorDispatch< type2,der >, processorDispatch< type3,der > {
processor p;
//make f visible - either
using processorDispatch< type1,der >::f;
using processorDispatch< type2,der >::f;
using processorDispatch< type3,der >::f;
//or
template <typename TYPE>
void f(TYPE t) {
processorDispatch<TYPE, der>::f(t);
}
}
};
结构顺序:processorDispatch以Kerrek的非CRTP解决方案为例,但“C++11免费”víA基类链接:
struct der_base {
processor p;
};
template <class TYPE, class Base = der_base>
struct der_t : Base, interface<TYPE> {
void f(TYPE t) { this->p.f(t); }
using Base::f;
};
template <class TYPE>
struct der_t<TYPE, der_base> : der_base, interface<TYPE> {
void f(TYPE t) { this->p.f(t); }
};
struct der_base{
处理器p;
};
模板
结构顺序:基础、接口{
void f(TYPE t){this->p.f(t);}
使用Base::f;
};
模板
数据结构:数据基,接口{
void f(TYPE t){this->p.f(t);}
};
然后使用
typedef der_t<type1, der_t<type2, der_t<type3> > > der;
typedef-der;
另一种解决方案,类似于@ArneMertz的解决方案,可能是(但是它涉及多个处理器实例
——每种类型一个,因此在某些情况下可能不合适):
为
类型
s创建基类型,并从接口继承
我想…我应该提到这一点-我不能更改类型X
,它们不在层次结构中。但仍然无法想象这会有什么帮助。我会考虑的,谢谢你的建议。好吧,如果他们不在层次结构中,这个想法就不值得追求:)好主意,我会在没有可变模板的情况下尝试。嗯,这可以在没有可变模板的情况下实现吗?@KerrekSB我想你应该使用der::f
在der
中,否则来自其他基的剩余f
将被隐藏而不是重载,对吗?@iavr:我也很奇怪,但为了通过多态基使用类,这不应该有什么区别。另外,在CRTP替代方案中,您需要使用变量声明:-)@KirilKirov:我在回答中提供了Kerrek第一个解的非变量方法。嗯,我也会尝试。听起来不错。我想在这种情况下,覆盖
不是必需的?不幸的是,我不能使用C++11
。当你有10多种类型时,“C++11免费非CRTP”解决方案会让使用变得很糟糕,但我明白了,谢谢!但是您确定处理器或数据库的方式吗?因为type1t1;d;d、 f(t1)
给了我一个模棱两可的调用。@KirilKirov我担心我离开了Kerrek的asnwer评论中提到的using指令。这当然是不幸的。@KirilKirov如果要继承许多接口,还可以编写一个模板函数,显式调用相应的dispatcher的f
(请参见我编辑的代码)。但是,这不允许隐式转换,例如,如果您仅从processorDispatch
继承,则调用d.f(42)
将产生编译错误,因为42
是int。@KirilKirov基类链接解决方案也需要使用指令。我添加了它,包括所需的专门化,因为deru base
没有f
。这是另一回事-处理器的模板实例现在是三个不同的对象,不共享内部状态。上面的所有解决方案都试图处理这样一个事实,即您在问题中只提到了一个单处理器对象;-)好吧,我的问题是,处理器可以被改变成任何东西,也可以是一个容器,里面有一个模板-d处理器,等等,但可能还不够清楚。其实没关系,只是想多分享一种方式。无论如何,谢谢你,你帮了我很多:)
struct type1 {};
struct type2 {};
struct type3 {};
template< typename TYPE >
struct interface
{
virtual void f( TYPE ) = 0;
};
template< typename TYPE >
struct processor
{
void f( TYPE t ){ std::cout << typeid( t ).name() << std::endl; }
};
template< typename TYPE >
struct interface_impl: interface< TYPE >
{
processor< TYPE > p_;
void f( TYPE t )
{
p_.f( t );
}
};
struct final: interface_impl< type1 >, interface_impl< type2 >, interface_impl< type3 >
{
template< typename TYPE >
void f( TYPE t )
{
interface_impl< TYPE >::f( t );
}
};
template< typename TYPE >
struct interface_impl: interface< TYPE >
{
struct processor
{
void f( TYPE t ){ std::cout << typeid( t ).name(); }
} p_;
void f( TYPE t )
{
p_.f( t );
}
};