如何实现可存储多种类型C++函数的FunctionPackage类?
实现支持存储任意类型函数的FunctionPackage
要解决不同签名函数的存储问题,核心思路是用类型擦除来统一存储任意类型的函数对象。C++17及以上可以直接用std::any实现,无需依赖宏,下面是具体方案:
修改后的FunctionPackage类
#include <unordered_map> #include <string> #include <any> #include <functional> #include <stdexcept> class FunctionPackage { public: // 模板注册函数,支持任意类型的函数/函数对象 template<typename T> void register_id(std::string name, T function) { functions[name] = function; } // 模板获取函数,需指定目标函数的签名类型 template<typename FuncType> FuncType get(const std::string& name) const { auto it = functions.find(name); if (it == functions.end()) { throw std::runtime_error("Function not found: " + name); } try { return std::any_cast<FuncType>(it->second); } catch (const std::bad_any_cast& e) { throw std::runtime_error("Function type mismatch for: " + name + ", error: " + e.what()); } } private: // 用std::any擦除类型,存储任意可拷贝的函数对象 std::unordered_map<std::string, std::any> functions; };
使用示例
#include <iostream> // 不同签名的测试函数 void func_void() { std::cout << "This is a void() function\n"; } int func_int(int x) { return x * 2; } std::string func_string(const std::string& s) { return "Hello, " + s; } int main() { FunctionPackage pkg; // 注册各种类型的函数(包括lambda) pkg.register_id("void_func", func_void); pkg.register_id("int_func", func_int); pkg.register_id("string_func", func_string); pkg.register_id("lambda", []() { std::cout << "Lambda function\n"; }); // 获取并调用函数,需明确指定签名类型 auto void_func = pkg.get<std::function<void()>>("void_func"); void_func(); auto int_func = pkg.get<std::function<int(int)>>("int_func"); std::cout << "int_func(5) = " << int_func(5) << "\n"; auto string_func = pkg.get<std::function<std::string(const std::string&)>>("string_func"); std::cout << string_func("World") << "\n"; auto lambda = pkg.get<std::function<void()>>("lambda"); lambda(); return 0; }
关键说明
- 类型擦除原理:
std::any可以存储任意可拷贝构造的对象,通过擦除具体类型,让不同签名的函数能存入同一个容器。 - 类型安全保障:获取函数时必须指定准确的签名类型(用
std::function<签名>),类型不匹配或函数不存在时会抛出异常,避免运行时错误。 - C++17之前的替代方案:如果无法使用C++17,可以手动实现类型擦除基类——定义一个空基类
FunctionWrapper,再为每个函数签名实现派生类,不过std::any的写法更简洁高效。
内容的提问来源于stack exchange,提问作者degawong
相关产品推荐
相关产品推荐

