如何实现无switch的ID-Lambda映射服务器dispatcher函数?
实现符合要求的
dispatcher()函数 核心思路
利用C++模板元编程在编译期构建ID与Lambda的映射关系,运行时通过接收的ID匹配对应的处理逻辑,完成参数接收、函数调用与结果发送的流程,全程无需switch语句,且每个dispatcher实例可绑定独立的函数集合。
完整实现代码
#include <utility> #include <vector> #include <tuple> #include <type_traits> #include <iostream> // 示例receive实现(实际需替换为真实的接收逻辑) template<class T> auto receive() { if constexpr (std::is_same_v<T, int>) { static int ids[] = {100, 1000, -1}; static size_t idx = 0; return ids[idx++]; } else if constexpr (std::is_same_v<T, std::vector<int>>) { return std::vector<int>{1, 2, 3}; } return T{}; } // 示例send实现(实际需替换为真实的发送逻辑) void send(auto&&... values) { ((std::cout << values << " "), ...); std::cout << "\n"; } // 辅助工具:提取函数的参数类型与返回类型 template<typename F> struct function_traits; template<typename R, typename... Args> struct function_traits<R(*)(Args...)> { using return_type = R; using args_tuple = std::tuple<Args...>; }; template<typename R, typename... Args> struct function_traits<R(Args...)> : function_traits<R(*)(Args...)> {}; template<typename F> struct function_traits : function_traits<decltype(&F::operator())> {}; template<typename C, typename R, typename... Args> struct function_traits<R(C::*)(Args...) const> : function_traits<R(*)(Args...)> {}; // 批量接收函数所需参数,打包为元组 template<typename... Args> std::tuple<Args...> receive_args() { return std::make_tuple(receive<Args>()...); } // 调用目标函数并发送返回结果 template<typename F> void invoke_and_send(F&& func) { using traits = function_traits<F>; auto args = receive_args<typename traits::args_tuple::value_type...>(); auto result = std::apply(std::forward<F>(func), args); send(std::move(result)); } // 绑定ID与对应处理逻辑的编译期单元 template<int Id, typename F> struct Handler { static constexpr int id = Id; static void handle() { invoke_and_send(F{}); } }; // 根据ID遍历匹配对应的处理单元并执行 template<typename... Handlers> void dispatch_by_id(int function_id) { (void)std::initializer_list<bool>{ (function_id == Handlers::id ? (Handlers::handle(), true) : false)... }; } // 最终的dispatcher模板函数 template<std::pair<int, auto>... Functions> void dispatcher() { for(auto function_id = 0; function_id != -1;) { function_id = receive<int>(); if (function_id == -1) break; dispatch_by_id<Handler<Functions.first, decltype(Functions.second)>...>(function_id); } } int main() { dispatcher< std::pair{100, []{ return 100; }}, std::pair{1000, [](const std::vector<int>& v){ return v.size(); }} >(); }
关键部分说明
- 函数类型提取:
function_traits结构体通过模板特化,从Lambda类型中提取出参数类型元组与返回类型,为后续参数接收提供类型依据。 - 参数接收与函数调用:
receive_args批量接收参数并打包为元组,invoke_and_send使用std::apply将参数元组传递给Lambda,调用后发送返回结果。 - 编译期映射构建:
Handler结构体将每个ID与对应的Lambda绑定为独立的处理单元,所有处理单元的信息在编译期确定。 - ID匹配逻辑:
dispatch_by_id通过初始化列表遍历所有Handler,匹配到对应ID后执行处理逻辑,完全避免了switch语句的使用。 - 独立实例支持:每个
dispatcher实例由模板参数传入的std::pair集合唯一确定,不同实例的函数集合相互独立。
内容的提问来源于stack exchange,提问作者Gene
相关产品推荐
相关产品推荐

