将实现注入单个多功能接口类 - 许多 CRTP 类?

cpp*_*ner 5 c++ interface crtp vtable c++14

如何创建多个类来充当接口类的实现者,同时尽可能避免 v-table 成本,并且仍然启用对接口的静态转换?

对于一个简单的情况,它可以像下面的例子一样实现。

例子

图书馆代码:-

class I{ //interface
    public: virtual void i1()=0;
};
template<class Derived>class Router : public I{ 
    public: virtual void  i1()final{   
        //in real case it is very complex, but in the core is calling :-
        static_cast<Derived*>(this)->u1(); 
    }
};
Run Code Online (Sandbox Code Playgroud)

用户代码:-

class User : public Router<User>{
    public: void u1(){ std::cout<<"hi"<<std::endl; }
};
int main() {
    User u;
    u.i1();   //<-- no v-table cost
    I* i=&u;
    i->i1();  //<-- has v-table cost (OK)
}
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

完整演示

如何扩展上述功能以支持 2 个或更多路由? 在此处输入图片说明

下面的代码无法编译,但它描绘了我的梦想。(完整演示)。

图书馆代码:-

class I{ //interface
    public: virtual void i1()=0;
    public: virtual void i2()=0;
};
template<class Derived>class RouterI1U1 : public I{ 
    public: virtual void  i1()final{ static_cast<Derived*>(this)->u1(); }
};
template<class Derived>class RouterI1U2 : public I{ 
    public: virtual void  i1()final{ static_cast<Derived*>(this)->u2(); }
};
template<class Derived>class RouterI2U1 : public I{ 
    public: virtual void  i2()final{ static_cast<Derived*>(this)->u1(); }
};
template<class Derived>class RouterI2U2 : public I{ 
    public: virtual void  i2()final{ static_cast<Derived*>(this)->u2(); }
};
Run Code Online (Sandbox Code Playgroud)

用户代码:-

想要使用上述库的人,可以轻松选择他想要的任何“路线”。

  • 源自RouterI1U2<User>RouterI2U1<User>
  • 源自RouterI1U1<User>RouterI2U2<User>
  • 派生自 {RouterI1U1<User>RouterI1U2<User>} 并i2()用 final 手动实现或
  • 派生自 {RouterI2U2<User>RouterI2U1<User>} 并i1()用 final 手动实现或
  • 手动实现i1()i2()最终

这是一个梦寐以求的用法示例。

class User : public RouterI1U2<User>,public RouterI2U1<User>{ 
    public: void u1(){ std::cout<<"hi1"<<std::endl; }
    public: void u2(){ std::cout<<"hi2"<<std::endl; }
};
int main() {
    User u;
    u.i1();   //<-- no v-table cost
    I* i=&u;
    i->i1();  //<-- has v-table cost (OK)
}
Run Code Online (Sandbox Code Playgroud)

我可怜的解决方案

class I{ //interface
    public: virtual void i1()=0;
    public: virtual void i2()=0;
};

template<class Derived> class RouterI1U2_I2U1 : public I{ //group it
    public: virtual void  i1()final{ static_cast<Derived*>(this)->u2(); }
    public: virtual void  i2()final{ static_cast<Derived*>(this)->u1(); }
};
class User : public RouterI1U2_I2U1<User>{ 
    public: void u1(){ std::cout<<"hi1"<<std::endl; }
    public: void u2(){ std::cout<<"hi2"<<std::endl; }
};
Run Code Online (Sandbox Code Playgroud)

它有效(演示),但提供较少的模块化。(低重用性)
我要包RouterI1U2RouterI2U1RouterI1U2_I2U1 手动。

n. *_* m. 1

使用虚拟继承。

template<class Derived>class RouterI1U1 : public virtual I{ 
Run Code Online (Sandbox Code Playgroud)

等等使代码可以编译。