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

如何存储构造函数传入的可变模板参数并实现类tuple的Storage类

实现动态参数存储类Storage

要实现一个无需提前指定类型、能存储任意参数包且可放入统一容器的类,核心思路是复用std::tuple做内部存储,配合类型擦除基类实现容器兼容性,具体实现如下:

1. 定义类型擦除基类

为了让不同参数类型的Storage实例能存入同一个容器,需要一个非模板基类:

#include <tuple>
#include <vector>
#include <memory>
#include <stdexcept>
#include <iostream>
#include <string>

// 非模板基类,用于实现类型擦除
class StorageBase {
public:
    virtual ~StorageBase() = default; // 虚析构确保子类资源正确释放
};

2. 实现Storage模板类

继承基类,用std::tuple存储参数包,同时提供类似std::get的索引访问方法:

template<typename... Args>
class Storage : public StorageBase {
private:
    std::tuple<Args...> data; // 内部用tuple存储参数

public:
    // 构造函数:完美转发参数包到tuple
    Storage(Args&&... args) : data(std::forward<Args>(args)...) {}

    // 按索引获取可变引用元素
    template<std::size_t Index>
    auto& get() {
        static_assert(Index < sizeof...(Args), "索引超出参数包范围");
        return std::get<Index>(data);
    }

    // 按索引获取const引用元素
    template<std::size_t Index>
    const auto& get() const {
        static_assert(Index < sizeof...(Args), "索引超出参数包范围");
        return std::get<Index>(data);
    }

    // 获取参数包的元素数量
    static constexpr std::size_t size() {
        return sizeof...(Args);
    }
};

3. 使用示例

演示如何创建实例、存入统一容器,以及访问元素:

int main() {
    // 创建不同参数类型的Storage实例
    auto storage_int_str = std::make_unique<Storage<int, std::string>>(5, "hello world");
    auto storage_double_bool = std::make_unique<Storage<double, bool>>(3.14, true);

    // 将不同实例存入同一个vector(存储基类智能指针)
    std::vector<std::unique_ptr<StorageBase>> storage_list;
    storage_list.push_back(std::move(storage_int_str));
    storage_list.push_back(std::move(storage_double_bool));

    // 访问第一个实例的元素:需动态转型到具体类型
    if (auto* s = dynamic_cast<Storage<int, std::string>*>(storage_list[0].get())) {
        std::cout << "第一个元素:" << s->get<0>() << ", " << s->get<1>() << "\n";
    }

    // 访问第二个实例的元素
    if (auto* s = dynamic_cast<Storage<double, bool>*>(storage_list[1].get())) {
        std::cout << "第二个元素:" << s->get<0>() << ", " << std::boolalpha << s->get<1>() << "\n";
    }

    return 0;
}

关键说明

  • 内部存储:直接用std::tuple处理参数包的类型推导和存储,无需手动实现复杂的类型存储逻辑。
  • 容器兼容性:通过非模板基类StorageBase实现类型擦除,让不同模板实例的Storage能存入同一个容器(需用指针/智能指针存储,避免对象切片)。
  • 元素访问:get方法通过模板索引配合std::get实现,静态断言能在编译期检查索引合法性;从容器取出元素时需用dynamic_cast转型到具体类型,这是类型擦除的必然代价——运行时必须明确存储的具体类型才能调用对应版本的get。
  • 性能优化:构造函数使用完美转发std::forward,减少不必要的拷贝操作。

内容的提问来源于stack exchange,提问作者TwistedBlizzard

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 07:57:14