使用std::any实现的double与int乘法函数编译失败求助
问题原因
你的代码无法正常执行乘法逻辑(实际是运行时抛出异常,并非编译错误),核心问题如下:
- 类型未被处理:乘法测试中你用
2.5f(float类型)初始化std::any c,但GenericBinaryOperation的分支仅覆盖了int、double和std::string类型,完全没有针对float的判断逻辑,因此会进入else分支抛出invalid_argument异常。 - 次要逻辑错误:字符串拼接部分错误传入了
add而非定义好的concatenate,虽不影响乘法逻辑,但会导致字符串拼接复用加法lambda。
解决方法
针对核心问题,有两种可行思路:
思路一:统一使用double类型
将2.5f改为2.5(double字面量),让std::any c存储double类型,匹配已有的double+int分支:
std::any c = 2.5;
思路二:扩展类型处理逻辑
在GenericBinaryOperation中增加对float类型的支持,可通过统一转换为double来复用现有逻辑,避免重复编写分支:
struct GenericBinaryOperation { template <typename Func> std::any operator()(const std::any& lhs, const std::any& rhs, Func&& func) const { // 统一将数值类型转换为double auto get_double = [](const std::any& val) -> double { if (val.type() == typeid(int)) return std::any_cast<int>(val); if (val.type() == typeid(double)) return std::any_cast<double>(val); if (val.type() == typeid(float)) return std::any_cast<float>(val); throw std::invalid_argument("Unsupported numeric type"); }; // 判断是否为数值类型组合 bool is_lhs_numeric = lhs.type() == typeid(int) || lhs.type() == typeid(double) || lhs.type() == typeid(float); bool is_rhs_numeric = rhs.type() == typeid(int) || rhs.type() == typeid(double) || rhs.type() == typeid(float); if (is_lhs_numeric && is_rhs_numeric) { return func(get_double(lhs), get_double(rhs)); } // 处理字符串拼接 else if (lhs.type() == typeid(std::string) && rhs.type() == typeid(std::string)) { return func(std::any_cast<std::string>(lhs), std::any_cast<std::string>(rhs)); } else { throw std::invalid_argument("Unsupported or mismatched types"); } } };
这种方式更灵活,能兼容更多数值类型组合。
修正后的完整代码
#include <iostream> #include <any> #include <stdexcept> #include <typeinfo> struct GenericBinaryOperation { template <typename Func> std::any operator()(const std::any& lhs, const std::any& rhs, Func&& func) const { // 统一将数值类型转换为double auto get_double = [](const std::any& val) -> double { if (val.type() == typeid(int)) return std::any_cast<int>(val); if (val.type() == typeid(double)) return std::any_cast<double>(val); if (val.type() == typeid(float)) return std::any_cast<float>(val); throw std::invalid_argument("Unsupported numeric type"); }; bool is_lhs_numeric = lhs.type() == typeid(int) || lhs.type() == typeid(double) || lhs.type() == typeid(float); bool is_rhs_numeric = rhs.type() == typeid(int) || rhs.type() == typeid(double) || rhs.type() == typeid(float); if (is_lhs_numeric && is_rhs_numeric) { return func(get_double(lhs), get_double(rhs)); } else if (lhs.type() == typeid(std::string) && rhs.type() == typeid(std::string)) { return func(std::any_cast<std::string>(lhs), std::any_cast<std::string>(rhs)); } else { throw std::invalid_argument("Unsupported or mismatched types"); } } }; int main() { GenericBinaryOperation operation; // Integer and double addition std::any a = 5; std::any b = 3.5; auto add = [](auto x, auto y) { return x + y; }; std::cout << "Add (int + double): " << std::any_cast<double>(operation(a, b, add)) << std::endl; // Float and integer multiplication std::any c = 2.5f; std::any d = 4; auto multiply = [](auto x, auto y) { return x * y; }; std::cout << "Multiply (float * int): " << std::any_cast<double>(operation(c, d, multiply)) << std::endl; // String concatenation std::any e = std::string("Hello, "); std::any f = std::string("World!"); auto concatenate = [](auto x, auto y) { return x + y; }; std::cout << "Concatenate (string + string): " << std::any_cast<std::string>(operation(e, f, concatenate)) << std::endl; // Example of mismatched types causing an exception try { std::any g = 42; std::any h = std::string("Forty-Two"); operation(g, h, add); // This will throw an exception due to type mismatch } catch (const std::invalid_argument& ex) { std::cerr << "Error: " << ex.what() << std::endl; } return 0; }
内容的提问来源于stack exchange,提问作者DeltaVega
相关产品推荐
相关产品推荐

