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

C++可变参数模板行类存储列模板类实现问题求助

问题描述

我正在通过自制RDBMS练习C++编程,设计了支持类型定制的模板化列结构column_impl,并尝试实现可变参数模板的row类来存储列,但当前代码无法正常运行。

row类代码

template <typename... col_types>
struct row {
  row(std::tuple<std::function<bool(col_types)>, bool, col_types>...col_data){
    int i = 0;
    ([&]{
        columns[i] = std::make_unique<column_impl<decltype(std::get<2>(col_data))>>(std::get<0>(col_data), std::get<1>(col_data), std::get<2>(col_data));
        i++;
    }(), ...);
  }
  std::array<std::unique_ptr<column_impl<col_types>>, sizeof...(col_types)> columns;
};

column_impl代码

template <typename data_t>
struct column_impl {
  column_impl<data_t>() {}
  column_impl<data_t>(std::function<bool(data_t)> _constraint) : constraint(_constraint) {}
  column_impl<data_t>(std::function<bool(data_t)> _constraint, bool _is_nullable)
      : constraint(_constraint), is_nullable(_is_nullable) {}

  // 此构造函数需要验证提供的数据是否满足约束,不满足则抛出异常
  column_impl<data_t>(std::function<bool(data_t)> _constraint, bool _is_nullable, data_t _value)
      : constraint(_constraint), is_nullable(_is_nullable) {
    if (validate_data()) {
      value = _value;
    } else {
      throw std::invalid_argument("Provided data couldn't satisfy column's constraint");
    }
  }

  std::function<bool(data_t)> constraint = [](data_t) { return true; };
  bool is_nullable = false;
  data_t value;
  auto get_column_type_variant() { return std::variant<data_t>(); }

  bool validate_data() { return constraint(value); }

  template <typename T>
  bool validate_type(T) {
    return std::is_nothrow_convertible<T, data_t>();
  }
};

我希望在row类中创建合适的列容器,实现能解包元组的构造函数,且不想使用vector。我考虑过用多态包装类,但不知如何实现,请问该如何解决这些问题?


解决方案

1. 实现多态基类解决异构存储问题

原row的std::array容器要求所有元素类型一致,但不同column_impl<col_types>是不同模板实例,无法直接存储。需要先定义非模板基类,让column_impl继承它:

// 列的通用基类,提供统一接口
struct column_base {
    virtual ~column_base() = default; // 必须声明虚析构,保证子类正确销毁
    virtual bool validate_data() = 0; // 通用验证接口
};

// 修改column_impl,继承column_base
template <typename data_t>
struct column_impl : public column_base {
    // 保留原有构造函数和成员变量

    // 重写基类虚函数
    bool validate_data() override {
        return constraint(value);
    }
};

2. 调整row的容器类型

将row的columns改为存储基类指针的std::array,这样就能容纳不同类型的column_impl实例:

template <typename... col_types>
struct row {
    // 构造函数后续修正
    std::array<std::unique_ptr<column_base>, sizeof...(col_types)> columns;
};

3. 修复构造函数的元组解包逻辑

原构造函数的折叠表达式求值顺序未定义,可能导致i的索引越界或顺序错误。改用编译期索引序列保证顺序:

template <typename... col_types>
struct row {
    row(std::tuple<std::function<bool(col_types)>, bool, col_types>... col_data) {
        // 用索引序列生成编译期确定的索引
        auto init_columns = [this]<std::size_t... Is>(std::index_sequence<Is...>, auto... data) {
            ( (columns[Is] = std::make_unique<column_impl<col_types>>(
                std::get<0>(data),
                std::get<1>(data),
                std::get<2>(data)
            )), ... );
        };
        init_columns(std::index_sequence_for<col_types...>{}, col_data...);
    }

    std::array<std::unique_ptr<column_base>, sizeof...(col_types)> columns;
};

4. 修正column_impl的构造函数验证逻辑

原构造函数中validate_data()调用时value未初始化,会检查垃圾值。需先赋值再验证:

column_impl<data_t>(std::function<bool(data_t)> _constraint, bool _is_nullable, data_t _value)
    : constraint(_constraint), is_nullable(_is_nullable), value(_value) { // 先初始化value
    if (!validate_data()) { // 再执行验证
        throw std::invalid_argument("Provided data couldn't satisfy column's constraint");
    }
}

5. 使用示例

// 定义列约束
auto age_constraint = [](int age) { return age > 18; };
auto name_constraint = [](const std::string& name) { return name.size() <= 20; };

// 创建row实例
row<int, std::string> user_row(
    std::make_tuple(age_constraint, false, 25),
    std::make_tuple(name_constraint, false, "Alice")
);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 08:59:17