如何使用一个map存储不同签名的函数以替换冗长的switch-case分支
超长switch-case重构方案
核心逻辑:所有需要第三个参数的调用,第三个参数都是当前函数内固定的字符串,无需动态传入可变参数,只需通过lambda包装将所有调用统一为相同签名的可调用对象即可。
方案1:std::map + lambda包装(适合type值不连续的场景)
直接将每个case的调用逻辑封装为仅接收a、b两个参数的std::function,固定参数通过lambda捕获:
#include <map> #include <functional> #include <string> // 假设func1、func2已有定义 void func1(int a, int b) { /* 原有实现 */ } void func2(int a, int b, const std::string& str) { /* 原有实现 */ } void func(int type, int a, int b) { const std::string str = "hello"; // 统一所有可调用对象的签名为 void(int,int) const std::map<int, std::function<void(int, int)>> func_map = { {1, [](int a, int b) { func1(a, b); }}, // 固定参数用值捕获,避免引用悬空问题 {2, [str](int a, int b) { func2(a, b, str); }}, // 其余数百个case只需按上述格式添加即可 }; auto iter = func_map.find(type); if (iter != func_map.end()) { iter->second(a, b); } else { // 此处添加原switch的default分支逻辑 } }
如果不需要每次调用都重新构造map,也可以将map改为静态变量,同时将固定的str也定义为静态常量即可。
方案2:数组/ std::array存储(适合type值连续的场景,性能更高)
如果type值是从1开始连续递增的整数,用数组替代map可以获得O(1)的查找效率:
#include <functional> #include <string> void func(int type, int a, int b) { const std::string str = "hello"; // 假设type最大值为200,下标0占位无实际作用 const std::function<void(int, int)> func_list[] = { nullptr, [](int a, int b) { func1(a, b); }, // type=1 [str](int a, int b) { func2(a, b, str); }, // type=2 // 其余case依次添加 }; constexpr int max_valid_type = sizeof(func_list) / sizeof(func_list[0]) - 1; if (type >= 1 && type <= max_valid_type && func_list[type]) { func_list[type](a, b); } else { // default逻辑 } }
上述两种方案都完全可以替代原有的switch结构,后续新增case只需在容器初始化列表中添加一行记录即可,无需修改核心调用逻辑,扩展性远强于原生switch。
内容的提问来源于stack exchange,提问作者Yves
相关产品推荐
相关产品推荐

