如何扩展Lambda参数包?将Lambda参数及返回值包装为变体/可选类型
问题:将Lambda转换为参数/返回值含std::variant或std::optional的版本
核心转换需求(std::variant版本)
我需要把如下形式的Lambda:
auto a = [](int b, std::string const& c) -> double { /* ... */ };
转换为:
auto aa = [](std::variant<int, int> b, std::variant<int, std::string> c) -> std::variant<int, double> { /* ... */ };
- 由于
std::variant无法存储引用,转换时可将原Lambda的参数改为值传递,或用std::remove_reference_t处理类型 - 实际输入的Lambda支持任意返回值(包括void)、任意数量参数(包括零个)、任意具体类型
备选转换需求(std::optional版本)
如果基于std::variant的实现有困难,也可接受转换为如下形式:
auto aa = [](std::optional<int> b, std::optional<std::string> c) -> std::optional<double> { /* ... */ };
我的尝试代码
Variant版本尝试
auto add_code = [](auto fn) -> std::variant<int, std::invoke_result_t<decltype(fn)>> { return [fn](std::variant<int, auto> ps...) { if ((ps.index() != 0 && ...)) { return { 0, fn(std::get<1>(ps)...) }; } else { return { 1 }; } }; };
Optional版本尝试
auto make_optional = [](auto fn) -> std::optional<std::invoke_result_t<decltype(fn)>> { return [fn](std::optional<auto> ps...) { if ((ps && ...)) { return { fn(*(ps)...) }; } else { return {}; } }; };
实现允许范围
- 可将实现封装在模板、带
operator()的结构体中,或拆分为多个Lambda/模板 - 若实现无法支持返回void或必须要求至少一个参数,我可自行补充适配逻辑
- 也允许用
std::pair或std::tuple替代std::variant - 要求基于C++20标准,兼容MSVC、GCC、Clang编译器
内容的提问来源于stack exchange,提问作者Chris Idzerda
相关产品推荐
相关产品推荐

