如何通过运行时枚举参数生成对应类型,简化C++类型擦除数组实现?
解决方案
针对你的需求,这里有两种更简洁的实现方式,无需将数组类模板化,同时支持根据运行时枚举参数处理对应类型:
方案一:用std::variant替代Union(C++17及以上)
std::variant是标准库提供的类型安全联合类型,无需手动管理内存和类型检查,比自定义Union更简洁可靠。核心思路是用variant存储不同类型的容器,通过std::visit匹配对应类型的操作。
示例代码
#include <variant> #include <vector> enum class DType { Int, Float, Double }; class AnyArray { private: // 用variant存储所有支持的数组类型 using Storage = std::variant<std::vector<int>, std::vector<float>, std::vector<double>>; Storage data_; DType dtype_; public: // 根据运行时枚举初始化对应类型的数组 AnyArray(DType dtype, size_t size) : dtype_(dtype) { switch(dtype) { case DType::Int: data_.emplace<std::vector<int>>(size); break; case DType::Float: data_.emplace<std::vector<float>>(size); break; case DType::Double: data_.emplace<std::vector<double>>(size); break; } } // 设置元素:用std::visit自动匹配对应类型的vector void set(size_t idx, double value) { std::visit([idx, value](auto& vec) { using ValueType = typename decltype(vec)::value_type; vec[idx] = static_cast<ValueType>(value); }, data_); } // 获取元素:统一返回double(也可以用variant返回原类型) double get(size_t idx) const { return std::visit([idx](const auto& vec) -> double { return static_cast<double>(vec[idx]); }, data_); } // 获取当前数组类型 DType dtype() const { return dtype_; } };
方案二:简化版类型擦除(继承+模板子类)
如果需要更灵活的扩展(比如添加更多类型专属操作),可以用抽象基类+模板实现类的方式,比传统继承方案更简洁:
示例代码
#include <vector> #include <memory> enum class DType { Int, Float, Double }; // 抽象接口类,定义统一操作 class ArrayInterface { public: virtual ~ArrayInterface() = default; virtual void set(size_t idx, double value) = 0; virtual double get(size_t idx) const = 0; virtual DType dtype() const = 0; }; // 模板实现类,针对具体类型做类型转换 template<typename ValueType> class ArrayImpl : public ArrayInterface { private: std::vector<ValueType> data_; DType dtype_; public: ArrayImpl(DType dtype, size_t size) : dtype_(dtype), data_(size) {} void set(size_t idx, double value) override { data_[idx] = static_cast<ValueType>(value); } double get(size_t idx) const override { return static_cast<double>(data_[idx]); } DType dtype() const override { return dtype_; } }; // 对外暴露的非模板数组类 class AnyArray { private: std::unique_ptr<ArrayInterface> impl_; public: AnyArray(DType dtype, size_t size) { // 根据运行时枚举创建对应类型的实现类实例 switch(dtype) { case DType::Int: impl_ = std::make_unique<ArrayImpl<int>>(dtype, size); break; case DType::Float: impl_ = std::make_unique<ArrayImpl<float>>(dtype, size); break; case DType::Double: impl_ = std::make_unique<ArrayImpl<double>>(dtype, size); break; } } // 转发操作到实现类 void set(size_t idx, double value) { impl_->set(idx, value); } double get(size_t idx) const { return impl_->get(idx); } DType dtype() const { return impl_->dtype(); } };
为什么std::conditional无法直接使用?
std::conditional是编译期模板工具,要求模板参数是constexpr(编译期常量),而你的枚举值是运行时参数,编译期无法确定其值,因此无法用它直接选择类型。上述两种方案都是通过运行时分支(switch)结合编译期模板生成的类型,实现了运行时类型选择的需求。
内容的提问来源于stack exchange,提问作者Sam Moldenha
相关产品推荐
相关产品推荐

