如何用std::variant重构向量运算的嵌套switch语句?
用std::variant实现简洁的向量加法
要替代原来基于union和嵌套switch的冗余代码,核心是利用std::visit自动处理std::variant的类型分支,结合模板函数复用不同向量类型的加法逻辑。
步骤1:实现通用向量加法模板
先写一个模板函数,统一处理同类型向量的加法逻辑,避免重复代码:
#include <variant> #include <vector> #include <algorithm> #include <stdexcept> #include <functional> template<typename T> std::vector<T> vector_add(const std::vector<T>& lhs, const std::vector<T>& rhs) { if (lhs.size() != rhs.size()) { throw std::invalid_argument("Vectors must have the same size"); } std::vector<T> result; result.reserve(lhs.size()); std::transform(lhs.begin(), lhs.end(), rhs.begin(), std::back_inserter(result), std::plus<T>()); return result; }
步骤2:实现add函数(严格类型匹配)
如果要求只能相加同类型的向量,用std::visit配合constexpr if做编译期类型检查:
using Data = std::variant<std::vector<int>, std::vector<float>, std::vector<double>>; Data add(const Data& lhs, const Data& rhs) { return std::visit([](const auto& l_vec, const auto& r_vec) -> Data { using LVecType = std::decay_t<decltype(l_vec)>; using RVecType = std::decay_t<decltype(r_vec)>; if constexpr (std::is_same_v<LVecType, RVecType>) { return vector_add(l_vec, r_vec); } else { throw std::invalid_argument("Cannot add vectors of different element types"); } }, lhs, rhs); }
可选:支持不同类型向量相加(自动转换)
如果需要支持不同数值类型的向量相加(比如int和float),可以利用std::common_type_t推导共同类型,实现混合加法:
// 混合类型向量加法模板 template<typename T, typename U> std::vector<std::common_type_t<T, U>> mixed_vector_add(const std::vector<T>& lhs, const std::vector<U>& rhs) { if (lhs.size() != rhs.size()) { throw std::invalid_argument("Vectors must have the same size"); } using CommonType = std::common_type_t<T, U>; std::vector<CommonType> result; result.reserve(lhs.size()); std::transform(lhs.begin(), lhs.end(), rhs.begin(), std::back_inserter(result), [](const T& a, const U& b) { return static_cast<CommonType>(a) + b; }); return result; } // 支持混合类型的add函数 Data add(const Data& lhs, const Data& rhs) { return std::visit([](const auto& l_vec, const auto& r_vec) -> Data { return mixed_vector_add(l_vec, r_vec); }, lhs, rhs); }
测试示例
#include <iostream> int main() { // 同类型相加 Data int_vec1 = std::vector<int>{1, 2, 3}; Data int_vec2 = std::vector<int>{4, 5, 6}; auto int_result = add(int_vec1, int_vec2); std::visit([](const auto& vec) { std::cout << "Int vector sum: "; for (auto num : vec) std::cout << num << " "; std::cout << "\n"; }, int_result); // 混合类型相加 Data float_vec = std::vector<float>{1.5f, 2.5f}; Data double_vec = std::vector<double>{3.0, 4.0}; auto mixed_result = add(float_vec, double_vec); std::visit([](const auto& vec) { std::cout << "Mixed vector sum: "; for (auto num : vec) std::cout << num << " "; std::cout << "\n"; }, mixed_result); }
为什么这比嵌套switch好?
- 无需手动编写大量重复的switch分支,新添加向量类型时只需扩展
Data的variant类型,加法逻辑无需修改 - 编译期类型检查,比union更安全,不会出现非法类型访问
- 模板函数复用了所有数值类型向量的加法逻辑,代码简洁易维护
内容的提问来源于stack exchange,提问作者Louis Strous
相关产品推荐
相关产品推荐

