You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现无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(); }}
    >();
}

关键部分说明

  1. 函数类型提取:function_traits结构体通过模板特化,从Lambda类型中提取出参数类型元组与返回类型,为后续参数接收提供类型依据。
  2. 参数接收与函数调用:receive_args批量接收参数并打包为元组,invoke_and_send使用std::apply将参数元组传递给Lambda,调用后发送返回结果。
  3. 编译期映射构建:Handler结构体将每个ID与对应的Lambda绑定为独立的处理单元,所有处理单元的信息在编译期确定。
  4. ID匹配逻辑:dispatch_by_id通过初始化列表遍历所有Handler,匹配到对应ID后执行处理逻辑,完全避免了switch语句的使用。
  5. 独立实例支持:每个dispatcher实例由模板参数传入的std::pair集合唯一确定,不同实例的函数集合相互独立。

内容的提问来源于stack exchange,提问作者Gene

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 22:29:57