0

I'm creating my own RDBMS to practice C++. I came up with a solution where each column can have a type and is a template. This is what a row looks like, but it doesn't work

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;
};

And here is a 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) {}

  // This constructor requires to validate whether provided data
  // satisfies provided constraint. If constraint isn't satisfied
  // an exception gets thrown. It needs to be handled
  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("Provived 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>();
  }
};

Any ideas how to create a container for columns inside of a row and create a constructor that unpacks tuples into a row? I can't get it working. I know this array is not supposed to work, but I have no idea how to write it better. And also I don't want a vector. I could write a polymorphic wrapper like
struct column{some_type_containing_column_impls column_obj;}, but I have no idea how to do it. And how to properly unpack those tuples into column_impl obj?

3
  • Looks to me like you're trying to create a std::array where each value is a different type? Unfortunately, C++ does not work this way. You'll need to find some other approach. Maybe a std::tuple-based approach. Commented Feb 18, 2023 at 13:08
  • Yes, as I said, this is not a proper approach. But I can't think of anything else and need help with it Commented Feb 18, 2023 at 13:09
  • Like I said, a tuple-based approach should work. But it would work in a completely different way. Commented Feb 18, 2023 at 15:06

1 Answer 1

0

Using only non-type template arguments can do the thing.

template<class T>
bool default_constraint(T) {
    return true;
}

template<class T, bool nullable = true, bool(constraint)(T) = default_constraint>
class column {
    T data;
    bool is_null;
public:
    column() : data(), is_null(true) { ///< T must be DefaultConstructable
        if (!validate())
            throw std::invalid_argument("Provided data couldn't satisfy column's constraint");
    }

    column(T data) : data(data), is_null(false) {
        if (!validate())
            throw std::invalid_argument("Provided data couldn't satisfy column's constraint");
    }

    bool validate() {
        return nullable || is_null || constraint(data);
    }

    T get() {
        return data;
    }
};

template<class... C>
struct row {
    std::tuple<C...> columns;

    row(C&&... c) : columns(std::forward<C>(c)...) {}

    template<int index>
    auto get() {
        return std::get<index>(columns).get();
    }
};

bool require_positive(int i) {
    return i >= 0;
}

int main() {
    typedef row<column<int>, column<float>, column<bool>> MyRow;
    MyRow r{1, 2.3f, true};

    using MyRow2 = row<column<int, false, require_positive>, column<float>>;
    MyRow2 r2{-1, 2.5}; ///< exception thrown
}

I know maybe you only want the "idea" of how to implement, but I just post the code here for clarity.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.