英文:
Variadic template class containing array of another template class
问题
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
objects?
英文:
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<br/>
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?
答案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
}
希望这有所帮助。如果您需要进一步的解释或翻译,请告诉我。
英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论