想做个自己的RPC网络库,其中有个功能是用函数名调用函数然后获取返回值。。。。。
原理比较简单:将[函数名字符串,函数指针]用hash存储起来就可以实现通过函数名字符串调用函数的想法。
但比较麻烦的一点是,如果函数返回类型不一样或者函数c参数不一样,那将无法存到hash里面。下面直接给出解决方法。
通过类class将函数包装起来,然后只需要实现函数名到类的实例(对象)的hash映射就可以了。
但是如何用同一个类包装不同的函数呢?答案是:继承
用基类F派生出FunctionObject,用FunctionObject实例化具体函数,然后强转成父类子针,hash里面存的是父类子针,也就类型一样了。
比较麻烦的是,当使用时必须把类型强转回来(为什么不能支持直接使用实际指向的对象呢)。下面附上代码
#include "../head.h"
void fun1(int x,int y){
cout<<x<<" "<<y<<endl;
}
int fun2(){
cout<<2<<endl;
return 1;
}
struct F {
virtual ~F() {}
};
template<typename Return,typename ...Args>
class FunctionObject:public F{
public:
function<Return(Args...)>ptr;
FunctionObject(function<Return(Args...)>const& f){
ptr=f;
}
};
class myFun{
public:
unordered_map<string,F*> myFunlist;
void init(){
myFunlist["fun1"]=new FunctionObject<void,int,int>(fun1);
myFunlist["fun2"]=new FunctionObject<int>(fun2);
}
template<typename ... _Args>
void run(string Fun ,_Args ... args){
(*static_cast<FunctionObject<int,_Args ...>*>(myFunlist[Fun])).ptr(args...);
}
};`
ps:使用了static_cast做了不安全的强制类型转换,如果使用较为安全的dy_cast,需要进行较为严格的控制,不然会运行时报错,例如返回值的类型是int强转成void时失败。
这里是主函数
#include "src/message.h"
#include "src/myfunction.h"
int main(){
// mymessage mm=mymessage(100,"da","dasd");
// mm.init();
// mm.addp("sd",2,3,4,"dad");
// cout<<"the input is"<<endl;
// mm.print_message();
// mymessage mm1=mymessage(mm.message_info);
// cout<<"the output is"<<endl;
// mm1.print_message();
// cout<<sizeof(mm1.ResponseId)<<endl;
myFun mf;
mf.init();
mf.run("fun1",1,2);
return 1;
}