将带有固定签名的自定义函数名注入 CRTP
inject a custom function-name with a fixed signature into CRTP
我想将一个 name 注入到 CRTP(Curiously recurring template pattern)base class 中,用于具有相当固定签名的待创建函数。
这是我现有的工作代码 (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 class 对,例如 B
和 BO
;他们有自己独特的自定义名称,用于类似 getBOUn()
的功能。
我可以用宏修复它,但我不想要另一层混乱。
请不要使用宏回答。
实际用例
我经常像这样创建 classes :-
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;
有时,我想以更抽象的方式访问 "some other functions" :-
dogOPtr->runNow(); //a custom function within WalkableO
我使用虚拟继承,因为如果我重新设计,例如每个 WalkableO
到 都是 HasHpO
,我可以像下面这样编辑代码。
我什至不需要更改 Dog
代码:-
struct WalkableO: Crtp<WalkableO,Walkable>, virtual HasHpO{/*something*/};
Dog
本身,可以是 BullDog
、TigerDog
等基础 class
遗憾的是,您声明新函数的选择非常有限。
在这种情况下,您要引入一个新的 identifier. After preprocessing, an identifier can only be introduced by a declaration. Under your constraints, the only three relevant kinds of declarations are simple-declarations, function-definitions, and template-declarations (on top of a declaration, which has to be a simple-declaration or function-definition in this case since it should declare a function). In a template-declaration, the only name(s) you declare is(are) the name(s) declared in the underlying simple-declaration or function-definition, so we are basically limited to simple-declarations and function-definitions. The names introduced by a simple-declaration or a function-definition are specified in its declarator,因此无法指定新的 标识符 并自动声明它。
换句话说,在C++中预处理后没有办法“透明地”传递待声明的标识符。因此,我认为您尝试做的事情是不可能的。您必须要么使用宏,要么自己声明函数。
我想将一个 name 注入到 CRTP(Curiously recurring template pattern)base class 中,用于具有相当固定签名的待创建函数。
这是我现有的工作代码 (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 class 对,例如 B
和 BO
;他们有自己独特的自定义名称,用于类似 getBOUn()
的功能。
我可以用宏修复它,但我不想要另一层混乱。
请不要使用宏回答。
实际用例
我经常像这样创建 classes :-
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;
有时,我想以更抽象的方式访问 "some other functions" :-
dogOPtr->runNow(); //a custom function within WalkableO
我使用虚拟继承,因为如果我重新设计,例如每个 WalkableO
到 都是 HasHpO
,我可以像下面这样编辑代码。
我什至不需要更改 Dog
代码:-
struct WalkableO: Crtp<WalkableO,Walkable>, virtual HasHpO{/*something*/};
Dog
本身,可以是 BullDog
、TigerDog
等基础 class
遗憾的是,您声明新函数的选择非常有限。
在这种情况下,您要引入一个新的 identifier. After preprocessing, an identifier can only be introduced by a declaration. Under your constraints, the only three relevant kinds of declarations are simple-declarations, function-definitions, and template-declarations (on top of a declaration, which has to be a simple-declaration or function-definition in this case since it should declare a function). In a template-declaration, the only name(s) you declare is(are) the name(s) declared in the underlying simple-declaration or function-definition, so we are basically limited to simple-declarations and function-definitions. The names introduced by a simple-declaration or a function-definition are specified in its declarator,因此无法指定新的 标识符 并自动声明它。
换句话说,在C++中预处理后没有办法“透明地”传递待声明的标识符。因此,我认为您尝试做的事情是不可能的。您必须要么使用宏,要么自己声明函数。