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

如何定义可存储不同签名lambda表达式的std::map?

如何在std::map中存储不同签名的Lambda表达式

当然有办法实现这个需求!既然你已经明确知道每个键对应的Lambda签名,我们可以借助C17提供的类型工具来统一map的value类型,同时兼容不同签名的函数。下面是两个在VS2017/C17环境下可正常编译的方案:

方案一:使用std::variant(类型安全首选)

std::variant是C++17引入的类型变体,它可以存储指定类型集合中的任意一种类型。我们可以把所有需要支持的std::function类型都放进variant里,作为map的value类型。

代码示例

#include <map>
#include <functional>
#include <variant>
#include <string>

// 定义包含所有需要的函数签名的variant类型
using FuncVariant = std::variant<
    std::function<bool(double)>,
    std::function<bool(double, double)>
>;

int main() {
    std::map<std::string, FuncVariant> func_map;

    // 插入不同签名的Lambda(自动匹配variant中的对应类型)
    func_map.emplace("gt_zero", [](double a) { return a > 0; });
    func_map.emplace("lt_zero", [](double a) { return a < 0; });
    func_map.emplace("equal", [](double a, double b) { return a == b; });

    // 调用时,根据已知的签名用std::get获取对应的函数
    bool foo = std::get<std::function<bool(double)>>(func_map["gt_zero"])(42); // 返回true
    bool bar = std::get<std::function<bool(double)>>(func_map["lt_zero"])(42); // 返回false
    bool baz = std::get<std::function<bool(double, double)>>(func_map["equal"])(42, 42); // 返回true

    // 安全调用方式(避免类型不匹配抛出异常)
    if (auto* gt_func = std::get_if<std::function<bool(double)>>(&func_map["gt_zero"])) {
        bool safe_foo = (*gt_func)(42);
    }

    return 0;
}

这个方案的优势是类型安全,编译期就能检查部分类型错误,而且调用时的语义清晰。

方案二:使用std::any(更灵活)

std::any是C++17引入的通用类型擦除容器,可以存储任意类型的对象。它比variant更灵活,但类型安全稍弱,需要你确保调用时的类型转换正确。

代码示例

#include <map>
#include <functional>
#include <any>
#include <string>

int main() {
    std::map<std::string, std::any> func_map;

    // 插入时显式转换为对应std::function类型(避免Lambda匿名类型导致的转换问题)
    func_map.emplace("gt_zero", std::function<bool(double)>([](double a) { return a > 0; }));
    func_map.emplace("equal", std::function<bool(double, double)>([](double a, double b) { return a == b; }));

    // 调用时用std::any_cast转换为对应的函数类型
    bool foo = std::any_cast<std::function<bool(double)>>(func_map["gt_zero"])(42);
    bool baz = std::any_cast<std::function<bool(double, double)>>(func_map["equal"])(42, 42);

    // 安全调用方式
    if (auto* eq_func = std::any_cast<std::function<bool(double, double)>>(&func_map["equal"])) {
        bool safe_baz = (*eq_func)(42, 42);
    }

    return 0;
}

注意事项

  1. 两个方案都需要在VS2017中开启C17编译选项(项目属性 -> C/C -> 语言 -> C++语言标准选择ISO C++17标准(/std:c++17))。
  2. 因为你已知每个键对应的签名,所以调用时一定要使用匹配的类型进行转换,否则会抛出std::bad_variant_access或std::bad_any_cast异常,建议使用std::get_if或std::any_cast的指针版本做安全检查。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 10:14:54