Python链式可调用转C++:支持不同返回类型的等价实现
在C++中实现动态链式类型转换操作
针对你从Python背景出发的需求,这里提供两种等价实现方案,支持每次调用返回不同类型,同时兼容通用参数传递:
方案1:使用std::any实现最大灵活性
std::any可以存储任意类型的值,完美模拟Python动态变量的特性,适合不确定中间类型范围的场景:
1. 定义通用参数结构
#include <any> #include <vector> #include <functional> #include <string> #include <iostream> #include <stdexcept> // 模拟Python的**kwargs,可根据业务需求扩展成员 struct CommonKwargs { bool verbose = false; std::string prefix = ""; // 可以添加更多通用参数,比如日志级别、超时时间等 };
2. 实现各操作类
每个操作类实现operator(),接收std::any输入和通用参数,处理后返回新的std::any:
struct AddOne { std::any operator()(const std::any& input, const CommonKwargs&) { if (const int* val = std::any_cast<int>(&input)) { return *val + 1; } throw std::invalid_argument("AddOne仅支持int类型输入"); } }; struct Stringify { std::any operator()(const std::any& input, const CommonKwargs&) { if (const int* val = std::any_cast<int>(&input)) { return std::to_string(*val); } throw std::invalid_argument("Stringify仅支持int类型输入"); } }; struct WrapNicely { std::any operator()(const std::any& input, const CommonKwargs& kwargs) { if (const std::string* s = std::any_cast<std::string>(&input)) { return kwargs.prefix + "result=" + *s; } throw std::invalid_argument("WrapNicely仅支持string类型输入"); } };
3. 链式执行主逻辑
int main() { std::any data = 42; CommonKwargs kwargs; kwargs.prefix = "["; // 设置通用参数示例 // 存储所有操作,统一调用接口 std::vector<std::function<std::any(std::any, const CommonKwargs&)>> operations = { AddOne{}, Stringify{}, WrapNicely{} }; // 循环执行链式操作 for (const auto& op : operations) { data = op(data, kwargs); } // 提取并输出最终结果 if (const std::string* result = std::any_cast<std::string>(&data)) { std::cout << *result << "]" << std::endl; // 输出:[result=43] } return 0; }
方案2:使用std::variant实现类型安全
如果能明确所有中间类型,推荐使用std::variant,它在编译时就会检查类型合法性,避免运行时类型错误:
1. 定义类型变体
#include <variant> // 预定义所有可能的中间类型 using DataVariant = std::variant<int, std::string>;
2. 适配操作类
修改操作类以接收和返回DataVariant:
struct AddOne { DataVariant operator()(const DataVariant& input, const CommonKwargs&) { if (std::holds_alternative<int>(input)) { return std::get<int>(input) + 1; } throw std::invalid_argument("AddOne仅支持int类型输入"); } }; struct Stringify { DataVariant operator()(const DataVariant& input, const CommonKwargs&) { if (std::holds_alternative<int>(input)) { return std::to_string(std::get<int>(input)); } throw std::invalid_argument("Stringify仅支持int类型输入"); } }; struct WrapNicely { DataVariant operator()(const DataVariant& input, const CommonKwargs& kwargs) { if (std::holds_alternative<std::string>(input)) { return kwargs.prefix + "result=" + std::get<std::string>(input); } throw std::invalid_argument("WrapNicely仅支持string类型输入"); } };
3. 链式执行逻辑
int main() { DataVariant data = 42; CommonKwargs kwargs; kwargs.prefix = "["; std::vector<std::function<DataVariant(DataVariant, const CommonKwargs&)>> operations = { AddOne{}, Stringify{}, WrapNicely{} }; for (const auto& op : operations) { data = op(data, kwargs); } if (std::holds_alternative<std::string>(data)) { std::cout << std::get<std::string>(data) << "]" << std::endl; } return 0; }
方案对比
std::any:灵活性拉满,支持任意类型,但需要手动做类型检查,运行时出错风险较高。std::variant:类型安全,编译期即可发现不匹配的类型问题,但需要预先定义所有可能的中间类型。
两种方案都完美复刻了Python中链式调用的逻辑,同时支持传递通用参数,可根据实际场景选择。
内容的提问来源于stack exchange,提问作者Jav
相关产品推荐
相关产品推荐

