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)
下面的代码无法编译,但它描绘了我的梦想。(完整演示)。
图书馆代码:-
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)
它有效(演示),但提供较少的模块化。(低重用性)
我要包RouterI1U2和RouterI2U1以RouterI1U2_I2U1 手动。
使用虚拟继承。
template<class Derived>class RouterI1U1 : public virtual I{
Run Code Online (Sandbox Code Playgroud)
等等使代码可以编译。