能否将泛型模板lambda作为std::function存入std::unordered_map?
可行,两种实现方案结合你的场景说明
核心逻辑说明
泛型lambda本质是一个带有模板化operator()的匿名类,要存入std::unordered_map,要么针对每个目标类型实例化出固定签名的std::function,要么利用C++17及以上的特性直接使用带auto参数的std::function,以下是具体实现:
方案1:C++17及以上(简洁版,推荐)
直接使用支持auto参数的std::function,无需手动实例化lambda的模板参数:
#include <iostream> #include <unordered_map> #include <functional> #include <tuple> #include <sstream> #include <string> #include <type_traits> int main() { // 泛型读取lambda:针对不同类型做编译期分支处理 auto read_lambda = [](auto& val, const std::string& line) { std::istringstream iss(line); if constexpr (std::is_same_v<std::decay_t<decltype(val)>, std::string>) { std::getline(iss >> std::ws, val); // 字符串读取整行(跳过前置空白) } else if constexpr (std::is_integral_v<std::decay_t<decltype(val)>>) { iss >> val; // 整数直接读取 } // 可扩展浮点数、自定义类型等分支 }; // 定义map:value为带auto参数的std::function,直接存入泛型lambda std::unordered_map<std::string, std::function<void(auto&, const std::string&)>> func_map; func_map["age"] = read_lambda; func_map["name"] = read_lambda; // 目标数据结构:std::tuple std::tuple<int, std::string> user_data; // 模拟扫描到的关键字和对应行数据 func_map["age"](std::get<0>(user_data), "30"); func_map["name"](std::get<1>(user_data), "Alice Smith"); // 验证结果 std::cout << "Age: " << std::get<0>(user_data) << "\n"; std::cout << "Name: " << std::get<1>(user_data) << "\n"; return 0; }
方案2:兼容C++14(手动实例化lambda)
C++14不支持std::function的auto参数,需针对每个目标类型,将泛型lambda实例化为固定签名的std::function,可结合std::variant统一存储不同签名的函数:
#include <iostream> #include <unordered_map> #include <functional> #include <tuple> #include <sstream> #include <string> #include <type_traits> #include <variant> int main() { auto read_lambda = [](auto& val, const std::string& line) { std::istringstream iss(line); if (std::is_same<std::decay_t<decltype(val)>, std::string>::value) { std::getline(iss >> std::ws, static_cast<std::string&>(val)); } else if (std::is_integral<std::decay_t<decltype(val)>>::value) { iss >> static_cast<int&>(val); } }; // 用variant封装不同签名的std::function using ReadFunc = std::variant< std::function<void(int&, const std::string&)>, std::function<void(std::string&, const std::string&)> >; std::unordered_map<std::string, ReadFunc> func_map; // 手动实例化lambda为对应类型的function并存入 func_map["age"] = static_cast<std::function<void(int&, const std::string&)>>(read_lambda); func_map["name"] = static_cast<std::function<void(std::string&, const std::string&)>>(read_lambda); std::tuple<int, std::string> user_data; // 用std::visit调用对应签名的函数 std::visit([&](auto&& func) { if constexpr (std::is_invocable_v<decltype(func), int&, const std::string&>) { func(std::get<0>(user_data), "30"); } }, func_map["age"]); std::visit([&](auto&& func) { if constexpr (std::is_invocable_v<decltype(func), std::string&, const std::string&>) { func(std::get<1>(user_data), "Alice Smith"); } }, func_map["name"]); std::cout << "Age: " << std::get<0>(user_data) << "\n"; std::cout << "Name: " << std::get<1>(user_data) << "\n"; return 0; }
内容的提问来源于stack exchange,提问作者A M
相关产品推荐
相关产品推荐

