c – Contaner为不同的功能?
发布时间:2020-12-16 05:21:17 所属栏目:百科 来源:网络整理
导读:我正在尝试为不同的函数实现一个容器类,我可以在其中保存函数指针,并在稍后调用这些函数.我会尽量解决我的问题更准确. 例如,我有2个不同的测试功能: int func1(int a,int b) { printf("func1 works! %i %in",a,b); return 0;}void func2(double a,double b
我正在尝试为不同的函数实现一个容器类,我可以在其中保存函数指针,并在稍后调用这些函数.我会尽量解决我的问题更准确.
例如,我有2个不同的测试功能: int func1(int a,int b) { printf("func1 works! %i %in",a,b); return 0; } void func2(double a,double b) { printf("func2 works! %.2lf %.2lfn",b); } 而且我也有数组变量,它们包含函数参数: std::vector<boost::variant<int,double>> args = {2.2,3.3}; 我决定使用我自己的functor类派生自一些基类(我想到使用虚拟方法): class BaseFunc { public: BaseFunc() {} ~BaseFunc() {} }; template <typename T> class Func; template <typename R,typename... Tn> class Func<R(Tn...)> : public BaseFunc { typedef R(*fptr_t)(Tn...); fptr_t fptr; public: Func() : fptr(nullptr) {} Func(fptr_t f) : fptr(f) {} R operator()(Tn... args) { return fptr(args...); } Func& operator=(fptr_t f) { fptr = f; return *this; } }; 另外我决定存储一些关于函数及其参数的信息: struct TypeInfo { int type_id; // for this example: 0 - int,1 - double template <class T> void ObtainType() { if (std::is_same<void,T>::value) type_id = 0; else if (std::is_same<int,T>::value) type_id = 1; else if (std::is_same<double,T>::value) type_id = 2; else type_id = -1; } }; struct FunctionInfo { public: FunctionInfo() {} FunctionInfo(BaseFunc *func,const TypeInfo& ret,std::vector<TypeInfo>& args) : func_ptr(func),return_info(ret) { args_info.swap(args); } ~FunctionInfo() { delete func_ptr; } BaseFunc * func_ptr; TypeInfo return_info; std::vector<TypeInfo> args_info; }; 所以现在我可以定义一个容器类: class Container { private: template <size_t n,typename... T> void ObtainTypeImpl(size_t i,TypeInfo& t) { if (i == n) t.ObtainType<std::tuple_element<n,std::tuple<T...>>::type>(); else if (n == sizeof...(T)-1) throw std::out_of_range("Tuple element out of range."); else ObtainTypeImpl<(n < sizeof...(T)-1 ? n + 1 : 0),T...>(i,t); } template <typename... T> void ObtainType(size_t i,TypeInfo& t) { return ObtainTypeImpl<0,t); } public: template <class R,class ...Args> void AddFunc(const std::string& str,R(*func)(Args...)) { BaseFunc * func_ptr = new Func<R(Args...)>(func); size_t arity = sizeof...(Args); TypeInfo ret; ret.ObtainType<R>(); std::vector<TypeInfo> args; args.resize(arity); for (size_t i = 0; i < arity; ++i) { ObtainType<Args...>(i,args[i]); } cont_[str] = FunctionInfo(func_ptr,ret,args); } void CallFunc(const std::string& func_name,std::vector<boost::variant<int,double>>& args_vec) { auto it = cont_.find(func_name); if (it != cont_.end()) { // ??????? // And here I stucked } } private: std::map<std::string,FunctionInfo> cont_; }; 然后我卡住了 >不知道如何从我的结构体获取函数类型信息:). 也许我的路径错了?你能建议任何解决这个问题,除了Lua这样的脚本引擎吗? 解决方法
你可以这样做:
class BaseFunc { public: virtual ~BaseFunc() = default; virtual void Call(std::vector<boost::variant<int,double>>& args_vec) const = 0; }; template <typename F> class Function; template <typename R,typename... Args> class Function<R(Args...)> : public BaseFunc { public: Function(R (*f)(Args...)) : f(f) {} void Call(std::vector<boost::variant<int,double>>& args_vec) const override { Call(args_vec,std::index_sequence_for<Args...>()); } private: template <std::size_t ... Is> void Call( std::vector<boost::variant<int,double>>& args_vec,std::index_sequence<Is...>) const { // Add additional check here if you want. f(boost::get<Args>(args_vec.at(Is))...); } private: R (*f)(Args...); }; Live example (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |