You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过运行时枚举参数生成对应类型,简化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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 19:10:27