【发布时间】:2020-02-03 04:31:10
【问题描述】:
我想将具有相当固定签名的待创建函数的 名称 注入到 CRTP(Curiously recurring template pattern)基类中。
这是我的现有代码 (coliru MCVE link) :-
#include <iostream>
#include <string>
//--- library layer ---
template<class O,class Under> struct Crtp{
Under* oNo=nullptr;
auto getUnderlying(){
return oNo;
}
};
//--- user layer ex 1 ---
struct B{ // please don't edit this class
int k=0;
};
struct BO : Crtp<BO,B>{
auto getBOUn(){ return Crtp<BO,B>::getUnderlying();}
// some other functions
};
//--- user layer ex 2 ---
struct C{ // please don't edit this class
int kad=0;
};
struct CO : Crtp<CO,C>{
auto getCOUn(){ return Crtp<CO,C>::getUnderlying();}
// some other functions
};
int main() {
BO bo; B b; bo.Crtp<BO,B>::oNo=&b; //<-- please don't edit
std::cout<< bo.getBOUn()->k;
}
我希望它会像这样简单:-
//--- user layer ex 1 ---
struct B{ // (same)
int k=0;
};
struct BO : Crtp<BO,B,getBOUn>{ //<--- so easy and clean
// some other functions
};
有可能吗,怎么做?
我有 >100 个类对,例如 B 和 BO ;他们对getBOUn()-like 函数有自己独特的自定义名称。
我可以用宏来修复它,但我不想要另一层混乱。
请不要使用宏回答。
真实用例
我经常创建这样的类:-
struct Walkable{
float stamina =0 ;
float speed =0;
};
struct WalkableO: Crtp<WalkableO,Walkable>{
auto getWalkUnderlying(){ return Crtp<BO,B>::getUnderlying();}
void runNow(){
if(getWalkUnderlying()->stamina >1 ){
getWalkUnderlying()->speed +=3;
getWalkUnderlying()->stamina --;
}
}
};
class Dog : public virtual WalkableO, public virtual HasHpO, public virtual EatenableO {};
有时,我喜欢直接访问特定的底层:-
Dog* dogPtr; /** some ini ...*/ dogPtr->getWalkUnderlying()->stamina=10;
有时,我想以更抽象的方式访问“其他一些功能”:-
dogOPtr->runNow(); //a custom function within WalkableO
我使用虚拟继承是因为如果我重新设计以制作例如每个 WalkableO 到 成为 HasHpO,我可以像下面这样编辑代码。
我什至不需要更改Dog 代码:-
struct WalkableO: Crtp<WalkableO,Walkable>, virtual HasHpO{/*something*/};
Dog 本身,可以是BullDog、TigerDog 等的基类
【问题讨论】:
-
为什么你需要在
BO中调用getUnderlying的函数?为什么不直接使用getUnderlying,省去很多麻烦呢?否则,CRTP 基础有点毫无意义。 -
“底层”指针的用途是什么?你在实施 pimpl 成语吗?如果是这样,我相信你能想出比
Crtp和getUnderlying更好的名字。 -
@Kerndog73 感谢您提出的好问题。我在我的帖子中回答它,因为这是我应该告诉的信息。我正在实现一个公共实现(与 pimpl 类似但不同)。
-
现在我明白了!你听说过实体-组件-系统架构吗?我为最好的 C++ ECS 框架之一做出了贡献(在我的书中,它是最好的),即EnTT。我强烈建议您查看 EnTT!您可以加入the Gitter chatroom与专家讨论EnTT。
-
@Kerndog73 哈,是的,我正在开发一个 ECS 库并将其用于我的游戏。感谢您的链接。