将具有固定签名的自定义函数名注入 CRTP

cpp*_*ner 2 c++ templates crtp c++17

我想将具有固定签名的待创建函数的名称注入到 CRTP(Curious recurring template pattern)基类中。

这是我现有的工作代码(coliru MCVE 链接):-

#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; 
}
Run Code Online (Sandbox Code Playgroud)

我希望它会很简单:-

//--- user layer ex 1 ---
struct B{  // (same)
    int k=0;
};
struct BO : Crtp<BO,B,getBOUn>{  //<--- so easy and clean
    // some other functions
};
Run Code Online (Sandbox Code Playgroud)

可能吗,怎么可能?

我有 >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 {};
Run Code Online (Sandbox Code Playgroud)

有时,我喜欢直接访问特定的底层代码:-

Dog* dogPtr; /** some ini ...*/ dogPtr->getWalkUnderlying()->stamina=10;
Run Code Online (Sandbox Code Playgroud)

有时,我想以更抽象的方式访问“其他一些功能”:-

dogOPtr->runNow();  //a custom function within WalkableO
Run Code Online (Sandbox Code Playgroud)

我使用虚拟继承,因为如果我重新设计,使例如每WalkableO到要 HasHpO过,我可以编辑如下面的代码。
我什至不需要更改Dog代码:-

struct WalkableO: Crtp<WalkableO,Walkable>, virtual HasHpO{/*something*/};
Run Code Online (Sandbox Code Playgroud)

Dog本身,可以是基类上BullDog,TigerDog等

L. *_* F. 5

不幸的是,您声明新函数的选择非常有限。

在这种情况下,您将引入一个新的identifier。之后预处理,一个识别符只能由一个引入的声明。在您的约束下,仅有的三种相关声明是simple-declaration s、function-definition s 和template-declaration s(在声明之上,在这种情况下必须是simple-declaration或function-definition因为它应该声明一个函数)。在模板声明中,,您声明的唯一名称是在底层中声明的名称simple-declaration或function-definition,所以我们基本上仅限于simple-declaration和function-definition。由简单声明或函数定义引入的名称在其declarator中指定,因此无法指定新标识符并自动声明它。

换句话说,在 C++ 中进行预处理后,无法“透明地”传递待声明的标识符。所以我不认为你想要做的事情是可能的。您必须使用宏,或自己声明函数。