From 8d0f3b3739b129e30f7b54d4a0ee0fe66e5ae639 Mon Sep 17 00:00:00 2001 From: Roland Bock Date: Sat, 8 Jun 2024 18:33:40 +0200 Subject: [PATCH] Clean up superfluous classes and functions And remove some remaining dynamic parts which were overlooked before. --- include/sqlpp11/compat/optional.h | 1 + include/sqlpp11/custom_query.h | 22 +- include/sqlpp11/detail/pick_arg.h | 22 +- include/sqlpp11/for_update.h | 78 +----- include/sqlpp11/from.h | 115 ++------ include/sqlpp11/group_by.h | 101 ++----- include/sqlpp11/having.h | 99 ++----- include/sqlpp11/insert.h | 9 +- include/sqlpp11/insert_value_list.h | 251 +++--------------- include/sqlpp11/into.h | 90 ++----- include/sqlpp11/limit.h | 77 +----- include/sqlpp11/mysql/remove.h | 23 +- include/sqlpp11/mysql/update.h | 21 +- include/sqlpp11/offset.h | 65 +---- include/sqlpp11/order_by.h | 100 ++----- include/sqlpp11/postgresql/insert.h | 24 +- include/sqlpp11/postgresql/on_conflict.h | 74 +----- .../postgresql/on_conflict_do_nothing.h | 35 +-- .../postgresql/on_conflict_do_update.h | 104 ++------ include/sqlpp11/postgresql/remove.h | 23 +- include/sqlpp11/postgresql/returning.h | 70 +---- .../postgresql/returning_column_list.h | 115 ++------ include/sqlpp11/postgresql/update.h | 14 +- include/sqlpp11/remove.h | 9 +- include/sqlpp11/select.h | 13 +- include/sqlpp11/select_column_list.h | 116 ++------ include/sqlpp11/select_flag_list.h | 102 ++----- include/sqlpp11/single_table.h | 85 ++---- include/sqlpp11/sqlite3/insert_or.h | 52 +--- include/sqlpp11/sqlite3/serializer.h | 4 +- include/sqlpp11/statement.h | 70 ++--- include/sqlpp11/statement_fwd.h | 2 +- include/sqlpp11/union.h | 113 ++------ include/sqlpp11/union_data.h | 6 +- include/sqlpp11/update.h | 7 +- include/sqlpp11/update_list.h | 100 ++----- include/sqlpp11/using.h | 98 ++----- include/sqlpp11/where.h | 172 +++--------- include/sqlpp11/with.h | 92 ++----- tests/core/serialize/CustomQuery.cpp | 6 +- tests/core/usage/CustomQuery.cpp | 13 +- tests/core/usage/Insert.cpp | 8 +- tests/core/usage/Interpret.cpp | 4 +- tests/core/usage/Ppgen.cpp | 4 +- tests/core/usage/Remove.cpp | 3 + tests/core/usage/is_regular.h | 23 +- tests/mysql/usage/DynamicSelect.cpp | 9 +- tests/mysql/usage/MoveConstructor.cpp | 13 +- tests/mysql/usage/Sample.cpp | 5 +- tests/postgresql/usage/Returning.cpp | 9 +- tests/sqlite3/usage/DynamicLoadingTest.cpp | 6 +- tests/sqlite3/usage/DynamicSelect.cpp | 16 +- tests/sqlite3/usage/Sample.cpp | 4 +- 53 files changed, 513 insertions(+), 2184 deletions(-) diff --git a/include/sqlpp11/compat/optional.h b/include/sqlpp11/compat/optional.h index 15deb245..8ad500c4 100644 --- a/include/sqlpp11/compat/optional.h +++ b/include/sqlpp11/compat/optional.h @@ -36,6 +36,7 @@ #include namespace sqlpp { +#warning move into compat? template using optional = std::optional; diff --git a/include/sqlpp11/custom_query.h b/include/sqlpp11/custom_query.h index f935c461..559a8c70 100644 --- a/include/sqlpp11/custom_query.h +++ b/include/sqlpp11/custom_query.h @@ -34,7 +34,7 @@ namespace sqlpp { - template + template struct custom_query_t; namespace detail @@ -50,20 +50,20 @@ namespace sqlpp using type = Clause; }; - template + template struct custom_parts_t { - using _custom_query_t = custom_query_t; + using _custom_query_t = custom_query_t; using _maybe_hidden_result_type_provider = detail::get_first_if; using _result_type_provider = typename unhide<_maybe_hidden_result_type_provider>::type; using _result_methods_t = typename _result_type_provider::template _result_methods_t<_result_type_provider>; }; } // namespace detail - template - struct custom_query_t : private detail::custom_parts_t::_result_methods_t + template + struct custom_query_t : private detail::custom_parts_t::_result_methods_t { - using _methods_t = typename detail::custom_parts_t::_result_methods_t; + using _methods_t = typename detail::custom_parts_t::_result_methods_t; using _traits = make_traits; using _nodes = detail::type_vector; @@ -113,7 +113,7 @@ namespace sqlpp } template - auto with_result_type_of(Part part) -> custom_query_t, Parts...> + auto with_result_type_of(Part part) -> custom_query_t, Parts...> { return {tuple_cat(std::make_tuple(hidden(part)), _parts)}; } @@ -121,18 +121,18 @@ namespace sqlpp std::tuple _parts; }; - template - Context& serialize(const custom_query_t& t, Context& context) + template + Context& serialize(const custom_query_t& t, Context& context) { interpret_tuple_without_braces(t._parts, " ", context); return context; } template - auto custom_query(Parts... parts) -> custom_query_t...> + auto custom_query(Parts... parts) -> custom_query_t...> { static_assert(sizeof...(Parts) > 0, "custom query requires at least one argument"); - return custom_query_t...>(parts...); + return custom_query_t...>(parts...); } } // namespace sqlpp diff --git a/include/sqlpp11/detail/pick_arg.h b/include/sqlpp11/detail/pick_arg.h index 495a72be..8b0944c7 100644 --- a/include/sqlpp11/detail/pick_arg.h +++ b/include/sqlpp11/detail/pick_arg.h @@ -32,23 +32,25 @@ namespace sqlpp { namespace detail { - template - typename Target::_data_t pick_arg_impl(Statement /* statement */, Term term, const std::true_type& /*unused*/) + template + const typename Clause::_data_t& pick_arg_impl(const OldStatement& /* old_statement */, const NewClauseData& new_data, const std::true_type& /*unused*/) { - return term; + return new_data; } - template - typename Target::_data_t pick_arg_impl(Statement statement, Term /* term */, const std::false_type& /*unused*/) + template + const typename Clause::_data_t& pick_arg_impl(const OldStatement& old_statement, const NewClauseData& /* new_data */, const std::false_type& /*unused*/) { - return Target::_get_member(statement)._data; + using old_policies_t = typename OldStatement::_policies_t; + using old_base_t = typename Clause::_base_t; + return static_cast(old_statement)._data; } - // Returns a statement's term either by picking the term from the statement or using the new term - template - typename Target::_data_t pick_arg(Statement statement, Term term) + // Returns a old_statement's new_data either by picking the new_data from the old_statement or using the new new_data + template + const typename Clause::_data_t& pick_arg(const OldStatement& old_statement, const NewClauseData& new_data) { - return pick_arg_impl(statement, term, std::is_same()); + return pick_arg_impl(old_statement, new_data, std::is_same::type>()); } } // namespace detail } // namespace sqlpp diff --git a/include/sqlpp11/for_update.h b/include/sqlpp11/for_update.h index e4734797..d29eb7c9 100644 --- a/include/sqlpp11/for_update.h +++ b/include/sqlpp11/for_update.h @@ -43,49 +43,17 @@ namespace sqlpp using _traits = make_traits; using _nodes = detail::type_vector<>; - // Data using _data_t = for_update_data_t; - // Member implementation with data and methods - template - struct _impl_t - { - // workaround for msvc bug https://connect.microsoft.com/VisualStudio/Feedback/Details/2091069 - _impl_t() = default; - _impl_t(const _data_t& data) : _data(data) - { - } - - _data_t _data; - }; - // Base template to be inherited by the statement template struct _base_t { - using _data_t = for_update_data_t; - - // workaround for msvc bug https://connect.microsoft.com/VisualStudio/Feedback/Details/2091069 - template - _base_t(Args&&... args) : for_update{std::forward(args)...} + _base_t(_data_t data) : _data{std::move(data)} { } - _impl_t for_update; - _impl_t& operator()() - { - return for_update; - } - const _impl_t& operator()() const - { - return for_update; - } - - template - static auto _get_member(T t) -> decltype(t.for_update) - { - return t.for_update; - } + _data_t _data; using _consistency_check = consistent_t; }; @@ -99,48 +67,16 @@ namespace sqlpp // Data using _data_t = no_data_t; - // Member implementation with data and methods - template - struct _impl_t - { - // workaround for msvc bug https://connect.microsoft.com/VisualStudio/Feedback/Details/2091069 - _impl_t() = default; - _impl_t(const _data_t& data) : _data(data) - { - } - - _data_t _data; - }; - // Base template to be inherited by the statement template struct _base_t { - using _data_t = no_data_t; - - // workaround for msvc bug https://connect.microsoft.com/VisualStudio/Feedback/Details/2091069 - template - _base_t(Args&&... args) : no_for_update{std::forward(args)...} + _base_t() = default; + _base_t(_data_t data) : _data{std::move(data)} { } - _impl_t no_for_update; - _impl_t& operator()() - { - return no_for_update; - } - const _impl_t& operator()() const - { - return no_for_update; - } - - template - static auto _get_member(T t) -> decltype(t.no_for_update) - { - return t.no_for_update; - } - - using _database_t = typename Policies::_database_t; + _data_t _data; template using _new_statement_t = new_statement_t; @@ -163,8 +99,8 @@ namespace sqlpp } template - auto for_update(T&& t) -> decltype(statement_t().for_update(std::forward(t))) + auto for_update(T&& t) -> decltype(statement_t().for_update(std::forward(t))) { - return statement_t().for_update(std::forward(t)); + return statement_t().for_update(std::forward(t)); } } // namespace sqlpp diff --git a/include/sqlpp11/from.h b/include/sqlpp11/from.h index ccef5d95..47dc63d8 100644 --- a/include/sqlpp11/from.h +++ b/include/sqlpp11/from.h @@ -36,76 +36,30 @@ namespace sqlpp { // FROM DATA - template + template struct from_data_t { - from_data_t(Table table) : _table(table) - { - } - - from_data_t(const from_data_t&) = default; - from_data_t(from_data_t&&) = default; - from_data_t& operator=(const from_data_t&) = default; - from_data_t& operator=(from_data_t&&) = default; - ~from_data_t() = default; - Table _table; }; // FROM - template + template struct from_t { using _traits = make_traits; using _nodes = detail::type_vector; - // Data - using _data_t = from_data_t; - - // Member implementation with data and methods - template - struct _impl_t - { - using _database_t = Database; - using _table_t = Table; - - // workaround for msvc bug https://connect.microsoft.com/VisualStudio/Feedback/Details/2091069 - _impl_t() = default; - _impl_t(const _data_t& data) : _data(data) - { - } - - public: - _data_t _data; - }; + using _data_t = from_data_t
; // Base template to be inherited by the statement template struct _base_t { - using _data_t = from_data_t; - - // workaround for msvc bug https://connect.microsoft.com/VisualStudio/Feedback/Details/2091069 - template - _base_t(Args&&... args) : from{std::forward(args)...} + _base_t(_data_t data) : _data{std::move(data)} { } - _impl_t from; - _impl_t& operator()() - { - return from; - } - const _impl_t& operator()() const - { - return from; - } - - template - static auto _get_member(T t) -> decltype(t.from) - { - return t.from; - } + _data_t _data; // FIXME: We might want to check if we have too many tables define in the FROM using _consistency_check = consistent_t; @@ -142,51 +96,18 @@ namespace sqlpp using _traits = make_traits; using _nodes = detail::type_vector<>; - // Data using _data_t = no_data_t; - // Member implementation with data and methods - template - struct _impl_t - { - // workaround for msvc bug https://connect.microsoft.com/VisualStudio/Feedback/Details/2091069 - _impl_t() = default; - _impl_t(const _data_t& data) : _data(data) - { - } - - _data_t _data; - }; - // Base template to be inherited by the statement template struct _base_t { - using _data_t = no_data_t; - - // workaround for msvc bug https://connect.microsoft.com/VisualStudio/Feedback/Details/2091069 - template - _base_t(Args&&... args) : no_from{std::forward(args)...} + _base_t() = default; + _base_t(_data_t data) : _data{std::move(data)} { } - _impl_t no_from; - _impl_t& operator()() - { - return no_from; - } - const _impl_t& operator()() const - { - return no_from; - } - - template - static auto _get_member(T t) -> decltype(t.no_from) - { - return t.no_from; - } - - using _database_t = typename Policies::_database_t; + _data_t _data; template using _new_statement_t = new_statement_t; @@ -194,29 +115,29 @@ namespace sqlpp using _consistency_check = consistent_t; template - auto from(Table table) const -> _new_statement_t, from_t>> + auto from(Table table) const -> _new_statement_t, from_t>> { using Check = check_from_static_t
; - return _from_impl(Check{}, table); + return _from_impl(Check{}, table); } private: - template + template auto _from_impl(Check, Table table) const -> inconsistent; - template + template auto _from_impl(consistent_t /*unused*/, Table table) const - -> _new_statement_t>> + -> _new_statement_t>> { return {static_cast&>(*this), - from_data_t>{from_table(table)}}; + from_data_t>{from_table(table)}}; } }; }; // Interpreters - template - Context& serialize(const from_data_t& t, Context& context) + template + Context& serialize(const from_data_t
& t, Context& context) { context << " FROM "; serialize(t._table, context); @@ -224,9 +145,9 @@ namespace sqlpp } template - auto from(T&& t) -> decltype(statement_t().from(std::forward(t))) + auto from(T&& t) -> decltype(statement_t().from(std::forward(t))) { - return statement_t().from(std::forward(t)); + return statement_t().from(std::forward(t)); } } // namespace sqlpp diff --git a/include/sqlpp11/group_by.h b/include/sqlpp11/group_by.h index b4f60625..c715df3f 100644 --- a/include/sqlpp11/group_by.h +++ b/include/sqlpp11/group_by.h @@ -36,7 +36,7 @@ namespace sqlpp { // GROUP BY DATA - template + template struct group_by_data_t { group_by_data_t(Expressions... expressions) : _expressions(expressions...) @@ -57,7 +57,7 @@ namespace sqlpp "at least one group-by expression requires a table which is otherwise not known in the statement"); // GROUP BY - template + template struct group_by_t { using _traits = make_traits; @@ -65,50 +65,17 @@ namespace sqlpp using _provided_aggregates = detail::make_type_set_t; - // Data - using _data_t = group_by_data_t; - - // Member implementation with data and methods - template - struct _impl_t - { - // workaround for msvc bug https://connect.microsoft.com/VisualStudio/Feedback/Details/2091069 - _impl_t() = default; - _impl_t(const _data_t& data) : _data(data) - { - } - - public: - _data_t _data; - }; + using _data_t = group_by_data_t; // Base template to be inherited by the statement template struct _base_t { - using _data_t = group_by_data_t; - - // workaround for msvc bug https://connect.microsoft.com/VisualStudio/Feedback/Details/2091069 - template - _base_t(Args&&... args) : group_by{std::forward(args)...} + _base_t(_data_t data) : _data{std::move(data)} { } - _impl_t group_by; - _impl_t& operator()() - { - return group_by; - } - const _impl_t& operator()() const - { - return group_by; - } - - template - static auto _get_member(T t) -> decltype(t.group_by) - { - return t.group_by; - } + _data_t _data; using _consistency_check = typename std::conditional::value, consistent_t, @@ -136,48 +103,16 @@ namespace sqlpp // Data using _data_t = no_data_t; - // Member implementation with data and methods - template - struct _impl_t - { - // workaround for msvc bug https://connect.microsoft.com/VisualStudio/Feedback/Details/2091069 - _impl_t() = default; - _impl_t(const _data_t& data) : _data(data) - { - } - - _data_t _data; - }; - // Base template to be inherited by the statement template struct _base_t { - using _data_t = no_data_t; - - // workaround for msvc bug https://connect.microsoft.com/VisualStudio/Feedback/Details/2091069 - template - _base_t(Args&&... args) : no_group_by{std::forward(args)...} + _base_t() = default; + _base_t(_data_t data) : _data{std::move(data)} { } - _impl_t no_group_by; - _impl_t& operator()() - { - return no_group_by; - } - const _impl_t& operator()() const - { - return no_group_by; - } - - template - static auto _get_member(T t) -> decltype(t.no_group_by) - { - return t.no_group_by; - } - - using _database_t = typename Policies::_database_t; + _data_t _data; template using _new_statement_t = new_statement_t; @@ -186,33 +121,33 @@ namespace sqlpp template auto group_by(Expressions... expressions) const - -> _new_statement_t, group_by_t> + -> _new_statement_t, group_by_t> { static_assert(sizeof...(Expressions), "at least one expression (e.g. a column) required in group_by()"); - return _group_by_impl(check_group_by_t{}, expressions...); + return _group_by_impl(check_group_by_t{}, expressions...); } private: - template + template auto _group_by_impl(Check, Expressions... expressions) const -> inconsistent; - template + template auto _group_by_impl(consistent_t /*unused*/, Expressions... expressions) const - -> _new_statement_t> + -> _new_statement_t> { static_assert(not detail::has_duplicates::value, "at least one duplicate argument detected in group_by()"); return {static_cast&>(*this), - group_by_data_t{expressions...}}; + group_by_data_t{expressions...}}; } }; }; // Interpreters - template - Context& serialize(const group_by_data_t& t, Context& context) + template + Context& serialize(const group_by_data_t& t, Context& context) { context << " GROUP BY "; interpret_tuple(t._expressions, ',', context); @@ -220,9 +155,9 @@ namespace sqlpp } template - auto group_by(T&&... t) -> decltype(statement_t().group_by(std::forward(t)...)) + auto group_by(T&&... t) -> decltype(statement_t().group_by(std::forward(t)...)) { - return statement_t().group_by(std::forward(t)...); + return statement_t().group_by(std::forward(t)...); } } // namespace sqlpp diff --git a/include/sqlpp11/having.h b/include/sqlpp11/having.h index dc17e5ea..4e9b122b 100644 --- a/include/sqlpp11/having.h +++ b/include/sqlpp11/having.h @@ -36,7 +36,7 @@ namespace sqlpp { // HAVING DATA - template + template struct having_data_t { having_data_t(Expression expression) : _expression(expression) @@ -60,56 +60,24 @@ namespace sqlpp "having expression not built out of aggregate expressions"); // HAVING - template + template struct having_t { using _traits = make_traits; using _nodes = detail::type_vector; // Data - using _data_t = having_data_t; - - // Member implementation with data and methods - template - struct _impl_t - { - // workaround for msvc bug https://connect.microsoft.com/VisualStudio/Feedback/Details/2091069 - _impl_t() = default; - _impl_t(const _data_t& data) : _data(data) - { - } - - public: - _data_t _data; - }; + using _data_t = having_data_t; // Base template to be inherited by the statement template struct _base_t { - using _data_t = having_data_t; - - // workaround for msvc bug https://connect.microsoft.com/VisualStudio/Feedback/Details/2091069 - template - _base_t(Args&&... args) : having{std::forward(args)...} + _base_t(_data_t data) : _data{std::move(data)} { } - _impl_t having; - _impl_t& operator()() - { - return having; - } - const _impl_t& operator()() const - { - return having; - } - - template - static auto _get_member(T t) -> decltype(t.having) - { - return t.having; - } + _data_t _data; using _table_check = typename std::conditional::value, consistent_t, @@ -159,48 +127,17 @@ namespace sqlpp // Data using _data_t = no_data_t; - // Member implementation with data and methods - template - struct _impl_t - { - // workaround for msvc bug https://connect.microsoft.com/VisualStudio/Feedback/Details/2091069 - _impl_t() = default; - _impl_t(const _data_t& data) : _data(data) - { - } - - _data_t _data; - }; - // Base template to be inherited by the statement template struct _base_t { - using _data_t = no_data_t; - - // workaround for msvc bug https://connect.microsoft.com/VisualStudio/Feedback/Details/2091069 - template - _base_t(Args&&... args) : no_having{std::forward(args)...} + _base_t() = default; + _base_t(_data_t data) : _data{std::move(data)} { } - _impl_t no_having; - _impl_t& operator()() - { - return no_having; - } - const _impl_t& operator()() const - { - return no_having; - } + _data_t _data; - template - static auto _get_member(T t) -> decltype(t.no_having) - { - return t.no_having; - } - - using _database_t = typename Policies::_database_t; // workaround for msvc bug https://connect.microsoft.com/VisualStudio/Feedback/Details/2173269 // template @@ -217,30 +154,30 @@ namespace sqlpp template auto having(Expression expression) const - -> _new_statement_t, having_t> + -> _new_statement_t, having_t> { using Check = check_having_static_t; - return _having_impl(Check{}, expression); + return _having_impl(Check{}, expression); } private: - template + template auto _having_impl(Check, Expression expression) const -> inconsistent; - template + template auto _having_impl(consistent_t /*unused*/, Expression expression) const - -> _new_statement_t> + -> _new_statement_t> { return {static_cast&>(*this), - having_data_t{expression}}; + having_data_t{expression}}; } }; }; // Interpreters - template - Context& serialize(const having_data_t& t, Context& context) + template + Context& serialize(const having_data_t& t, Context& context) { context << " HAVING "; serialize(t._expression, context); @@ -248,9 +185,9 @@ namespace sqlpp } template - auto having(T&& t) -> decltype(statement_t().having(std::forward(t))) + auto having(T&& t) -> decltype(statement_t().having(std::forward(t))) { - return statement_t().having(std::forward(t)); + return statement_t().having(std::forward(t)); } } // namespace sqlpp diff --git a/include/sqlpp11/insert.h b/include/sqlpp11/insert.h index a9066c70..d0c80bb7 100644 --- a/include/sqlpp11/insert.h +++ b/include/sqlpp11/insert.h @@ -95,18 +95,17 @@ namespace sqlpp return context; } - template - using blank_insert_t = statement_t; + using blank_insert_t = statement_t; - inline auto insert() -> blank_insert_t + inline auto insert() -> blank_insert_t { return {}; } template - constexpr auto insert_into(Table table) -> decltype(blank_insert_t().into(table)) + constexpr auto insert_into(Table table) -> decltype(blank_insert_t().into(table)) { - return {blank_insert_t().into(table)}; + return {blank_insert_t().into(table)}; } } // namespace sqlpp diff --git a/include/sqlpp11/insert_value_list.h b/include/sqlpp11/insert_value_list.h index 4c1a62a5..0e2e7e04 100644 --- a/include/sqlpp11/insert_value_list.h +++ b/include/sqlpp11/insert_value_list.h @@ -73,52 +73,21 @@ namespace sqlpp // Data using _data_t = insert_default_values_data_t; - // Member implementation with data and methods - template - struct _impl_t - { - // workaround for msvc bug https://connect.microsoft.com/VisualStudio/Feedback/Details/2091069 - _impl_t() = default; - _impl_t(const _data_t& data) : _data(data) - { - } - - _data_t _data; - }; - // Base template to be inherited by the statement template struct _base_t { - using _data_t = insert_default_values_data_t; - - // workaround for msvc bug https://connect.microsoft.com/VisualStudio/Feedback/Details/2091069 - template - _base_t(Args&&... args) : default_values{std::forward(args)...} + _base_t(_data_t data) : _data{std::move(data)} { } - _impl_t default_values; - _impl_t& operator()() - { - return default_values; - } - const _impl_t& operator()() const - { - return default_values; - } - - template - static auto _get_member(T t) -> decltype(t.default_values) - { - return t.default_values; - } + _data_t _data; using _consistency_check = consistent_t; }; }; - template + template struct insert_list_data_t { insert_list_data_t(std::tuple assignments) @@ -229,110 +198,33 @@ namespace sqlpp template using check_insert_static_set_t = typename check_insert_static_set::type; - // workaround for msvc bug https://connect.microsoft.com/VisualStudio/Feedback/Details/2173269 - // template - // using check_insert_dynamic_set_t = static_combined_check_t< - // static_check_t::value, assert_insert_dynamic_set_statement_dynamic_t>, - // check_insert_set_t>; - template - struct check_insert_dynamic_set - { - using type = static_combined_check_t< - static_check_t::value, assert_insert_dynamic_set_statement_dynamic_t>, - check_insert_set_t>; - }; - - template - using check_insert_dynamic_set_t = typename check_insert_dynamic_set::type; - SQLPP_PORTABLE_STATIC_ASSERT( assert_no_unknown_tables_in_insert_assignments_t, "at least one insert assignment requires a table which is otherwise not known in the statement"); - template + template struct insert_list_t { using _traits = make_traits; using _nodes = detail::type_vector..., rhs_t...>; - using _is_dynamic = is_database; - template