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
相关产品推荐
相关产品推荐

