diff --git a/dev/ast/group_by.h b/dev/ast/group_by.h index c2deeb54c..7a6b3ff62 100644 --- a/dev/ast/group_by.h +++ b/dev/ast/group_by.h @@ -1,17 +1,16 @@ #pragma once -#include // std::tuple, std::make_tuple -#include // std::true_type, std::false_type #include // std::forward, std::move #include "../functional/cxx_type_traits_polyfill.h" +#include "../functional/tuple.h" namespace sqlite_orm { namespace internal { template struct group_by_with_having { - using args_type = std::tuple; + using args_type = mpl::tuple; using expression_type = T; args_type args; @@ -23,7 +22,7 @@ namespace sqlite_orm { */ template struct group_by_t { - using args_type = std::tuple; + using args_type = mpl::tuple; args_type args; @@ -58,7 +57,7 @@ namespace sqlite_orm { */ template internal::group_by_t group_by(Args&&... args) { - return {std::make_tuple(std::forward(args)...)}; + return {mpl::make_tuple(std::forward(args)...)}; } /** diff --git a/dev/ast/upsert_clause.h b/dev/ast/upsert_clause.h index f46a293b6..ab190d110 100644 --- a/dev/ast/upsert_clause.h +++ b/dev/ast/upsert_clause.h @@ -1,10 +1,9 @@ #pragma once -#include // std::tuple, std::make_tuple -#include // std::false_type, std::true_type #include // std::forward, std::move #include "../functional/cxx_type_traits_polyfill.h" +#include "../functional/tuple.h" namespace sqlite_orm { namespace internal { @@ -14,24 +13,24 @@ namespace sqlite_orm { template struct conflict_target { - using args_tuple = std::tuple; + using args_tuple = mpl::tuple; args_tuple args; - upsert_clause> do_nothing() { - return {move(this->args), {}}; + upsert_clause> do_nothing() { + return {std::move(this->args), {}}; } template - upsert_clause> do_update(ActionsArgs... actions) { - return {move(this->args), {std::make_tuple(std::forward(actions)...)}}; + upsert_clause> do_update(ActionsArgs... actions) { + return {std::move(this->args), {std::forward(actions)...}}; } }; template - struct upsert_clause, std::tuple> { - using target_args_tuple = std::tuple; - using actions_tuple = std::tuple; + struct upsert_clause, mpl::tuple> { + using target_args_tuple = mpl::tuple; + using actions_tuple = mpl::tuple; target_args_tuple target_args; @@ -56,7 +55,7 @@ namespace sqlite_orm { */ template internal::conflict_target on_conflict(Args... args) { - return {std::tuple(std::forward(args)...)}; + return {{std::forward(args)...}}; } #endif } diff --git a/dev/ast_iterator.h b/dev/ast_iterator.h index 460ec8507..4981ec3ef 100644 --- a/dev/ast_iterator.h +++ b/dev/ast_iterator.h @@ -96,8 +96,8 @@ namespace sqlite_orm { }; template - struct ast_iterator, std::tuple>, void> { - using node_type = upsert_clause, std::tuple>; + struct ast_iterator, mpl::tuple>, void> { + using node_type = upsert_clause, mpl::tuple>; template void operator()(const node_type& expression, L& lambda) const { @@ -318,6 +318,18 @@ namespace sqlite_orm { } }; + template + struct ast_iterator, void> { + using node_type = mpl::tuple; + + template + void operator()(const node_type& node, L& lambda) const { + iterate_tuple(node, [&lambda](auto& v) { + iterate_ast(v, lambda); + }); + } + }; + template struct ast_iterator, void> { using node_type = group_by_with_having; diff --git a/dev/column.h b/dev/column.h index 276f1c181..bdc8c7c1e 100644 --- a/dev/column.h +++ b/dev/column.h @@ -1,12 +1,13 @@ #pragma once -#include // std::tuple #include // std::string #include // std::unique_ptr #include // std::is_same, std::is_member_object_pointer #include "functional/cxx_universal.h" #include "functional/cxx_type_traits_polyfill.h" +#include "functional/fast_and.h" +#include "functional/unique_tuple.h" #include "tuple_helper/tuple_traits.h" #include "tuple_helper/tuple_filter.h" #include "type_traits.h" @@ -46,13 +47,12 @@ namespace sqlite_orm { * Member pointer used to read a field value. * If it is a object member pointer it is also used to write a field value. */ - const member_pointer_t member_pointer; + member_pointer_t member_pointer; /** * Setter member function to write a field value */ - SQLITE_ORM_NOUNIQUEADDRESS - const setter_type setter; + SQLITE_ORM_NOUNIQUEADDRESS const setter_type setter; /** * Simplified interface for `NOT NULL` constraint @@ -69,10 +69,9 @@ namespace sqlite_orm { */ template struct column_constraints { - using constraints_type = std::tuple; + using constraints_type = mpl::uple; - SQLITE_ORM_NOUNIQUEADDRESS - constraints_type constraints; + SQLITE_ORM_NOUNIQUEADDRESS constraints_type constraints; /** * Checks whether contraints are of trait `Trait` @@ -105,9 +104,9 @@ namespace sqlite_orm { template struct column_t : column_identifier, column_field, column_constraints { #ifndef SQLITE_ORM_AGGREGATE_BASES_SUPPORTED - column_t(std::string name, G memberPointer, S setter, std::tuple op) : + column_t(std::string name, G memberPointer, S setter, mpl::uple op) : column_identifier{move(name)}, column_field{memberPointer, setter}, column_constraints{ - move(op)} {} + std::move(op)} {} #endif }; @@ -142,9 +141,9 @@ namespace sqlite_orm { */ template = true> internal::column_t make_column(std::string name, M m, Op... constraints) { - static_assert(polyfill::conjunction_v...>, "Incorrect constraints pack"); + static_assert(SQLITE_ORM_FAST_AND(internal::is_constraint), "Incorrect constraints pack"); - SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES(return {move(name), m, {}, std::make_tuple(constraints...)}); + SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES(return {move(name), m, {}, mpl::make_unique_tuple(constraints...)}); } /** @@ -158,9 +157,10 @@ namespace sqlite_orm { internal::column_t make_column(std::string name, S setter, G getter, Op... constraints) { static_assert(std::is_same, internal::getter_field_type_t>::value, "Getter and setter must get and set same data type"); - static_assert(polyfill::conjunction_v...>, "Incorrect constraints pack"); + static_assert(SQLITE_ORM_FAST_AND(internal::is_constraint), "Incorrect constraints pack"); - SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES(return {move(name), getter, setter, std::make_tuple(constraints...)}); + SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES( + return {move(name), getter, setter, mpl::make_unique_tuple(constraints...)}); } /** @@ -175,8 +175,9 @@ namespace sqlite_orm { internal::column_t make_column(std::string name, G getter, S setter, Op... constraints) { static_assert(std::is_same, internal::getter_field_type_t>::value, "Getter and setter must get and set same data type"); - static_assert(polyfill::conjunction_v...>, "Incorrect constraints pack"); + static_assert(SQLITE_ORM_FAST_AND(internal::is_constraint), "Incorrect constraints pack"); - SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES(return {move(name), getter, setter, std::make_tuple(constraints...)}); + SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES( + return {move(name), getter, setter, mpl::make_unique_tuple(constraints...)}); } } diff --git a/dev/conditions.h b/dev/conditions.h index 873776481..bc16fe1c5 100644 --- a/dev/conditions.h +++ b/dev/conditions.h @@ -3,11 +3,13 @@ #include // std::string #include // std::enable_if, std::is_same #include // std::vector -#include // std::tuple, std::tuple_size #include // std::stringstream +#include // std::move #include "functional/cxx_universal.h" #include "functional/cxx_type_traits_polyfill.h" +#include "functional/pack.h" +#include "functional/tuple.h" #include "type_traits.h" #include "collate_argument.h" #include "constraints.h" @@ -376,7 +378,7 @@ namespace sqlite_orm { template struct in_t : condition_t, in_base, negatable_t { L left; - std::tuple argument; + mpl::tuple argument; in_t(L left_, decltype(argument) argument_, bool negative_) : in_base{negative_}, left(std::move(left_)), argument(std::move(argument_)) {} @@ -497,7 +499,7 @@ namespace sqlite_orm { */ template struct multi_order_by_t : order_by_string { - using args_type = std::tuple; + using args_type = mpl::tuple; args_type args; @@ -796,7 +798,7 @@ namespace sqlite_orm { template struct from_t { - using tuple_type = std::tuple; + using pack_type = mpl::pack; }; template @@ -809,7 +811,7 @@ namespace sqlite_orm { */ template internal::from_t from() { - static_assert(std::tuple_size>::value > 0, ""); + static_assert(sizeof...(Args) > 0, ""); return {}; } @@ -1196,7 +1198,7 @@ namespace sqlite_orm { */ template internal::multi_order_by_t multi_order_by(Args&&... args) { - return {std::make_tuple(std::forward(args)...)}; + return {mpl::make_tuple(std::forward(args)...)}; } /** diff --git a/dev/constraints.h b/dev/constraints.h index d377f4a9e..237b5e506 100644 --- a/dev/constraints.h +++ b/dev/constraints.h @@ -3,12 +3,12 @@ #include // std::system_error #include // std::ostream #include // std::string -#include // std::tuple, std::make_tuple -#include // std::is_base_of, std::false_type, std::true_type +#include // std::is_base_of, std::false_type #include "functional/cxx_universal.h" #include "functional/cxx_type_traits_polyfill.h" #include "functional/mpl.h" +#include "functional/tuple.h" #include "tuple_helper/same_or_void.h" #include "tuple_helper/tuple_traits.h" #include "tuple_helper/tuple_filter.h" @@ -60,11 +60,11 @@ namespace sqlite_orm { template struct primary_key_t : primary_key_base { using order_by = primary_key_base::order_by; - using columns_tuple = std::tuple; + using columns_tuple = mpl::tuple; columns_tuple columns; - primary_key_t(decltype(columns) c) : columns(move(c)) {} + primary_key_t(decltype(columns) c) : columns(std::move(c)) {} primary_key_t asc() const { auto res = *this; @@ -90,11 +90,11 @@ namespace sqlite_orm { */ template struct unique_t : unique_base { - using columns_tuple = std::tuple; + using columns_tuple = mpl::tuple; columns_tuple columns; - unique_t(columns_tuple columns_) : columns(move(columns_)) {} + unique_t(columns_tuple columns_) : columns(std::move(columns_)) {} }; /** @@ -243,9 +243,9 @@ namespace sqlite_orm { } template - struct foreign_key_t, std::tuple> { - using columns_type = std::tuple; - using references_type = std::tuple; + struct foreign_key_t, mpl::tuple> { + using columns_type = mpl::tuple; + using references_type = mpl::tuple; using self = foreign_key_t; /** @@ -269,7 +269,7 @@ namespace sqlite_orm { static_assert(!std::is_same::value, "All references must have the same type"); foreign_key_t(columns_type columns_, references_type references_) : - columns(move(columns_)), references(move(references_)), + columns(std::move(columns_)), references(std::move(references_)), on_update(*this, true, foreign_key_action::none), on_delete(*this, false, foreign_key_action::none) {} foreign_key_t(const self& other) : @@ -298,13 +298,13 @@ namespace sqlite_orm { */ template struct foreign_key_intermediate_t { - using tuple_type = std::tuple; + using tuple_type = mpl::tuple; tuple_type columns; template - foreign_key_t, std::tuple> references(Rs... refs) { - return {std::move(this->columns), std::make_tuple(std::forward(refs)...)}; + foreign_key_t, mpl::tuple> references(Rs... refs) { + return {std::move(this->columns), mpl::make_tuple(std::forward(refs)...)}; } }; #endif @@ -449,7 +449,7 @@ namespace sqlite_orm { */ template internal::foreign_key_intermediate_t foreign_key(Cs... columns) { - return {std::make_tuple(std::forward(columns)...)}; + return {mpl::make_tuple(std::forward(columns)...)}; } #endif @@ -458,7 +458,7 @@ namespace sqlite_orm { */ template internal::unique_t unique(Args... args) { - return {std::make_tuple(std::forward(args)...)}; + return {mpl::make_tuple(std::forward(args)...)}; } inline internal::unique_t<> unique() { @@ -471,7 +471,7 @@ namespace sqlite_orm { template internal::primary_key_t primary_key(Cs... cs) { - return {std::make_tuple(std::forward(cs)...)}; + return {mpl::make_tuple(std::forward(cs)...)}; } inline internal::primary_key_t<> primary_key() { diff --git a/dev/core_functions.h b/dev/core_functions.h index 1c4a896d9..4db212115 100644 --- a/dev/core_functions.h +++ b/dev/core_functions.h @@ -1,12 +1,12 @@ #pragma once #include // std::string -#include // std::make_tuple, std::tuple_size #include // std::forward, std::is_base_of, std::enable_if #include // std::unique_ptr #include // std::vector #include "functional/cxx_type_traits_polyfill.h" +#include "functional/tuple.h" #include "conditions.h" #include "is_base_of_template.h" #include "tuple_helper/tuple_filter.h" @@ -34,7 +34,7 @@ namespace sqlite_orm { struct built_in_function_t : S, arithmetic_t { using return_type = R; using string_type = S; - using args_type = std::tuple; + using args_type = mpl::tuple; static constexpr size_t args_size = std::tuple_size::value; @@ -662,7 +662,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t acos(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -678,7 +678,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t acos(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -690,7 +690,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t acosh(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -706,7 +706,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t acosh(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -718,7 +718,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t asin(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -734,7 +734,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t asin(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -746,7 +746,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t asinh(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -762,7 +762,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t asinh(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -774,7 +774,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t atan(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -790,7 +790,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t atan(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -802,7 +802,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t atan2(X x, Y y) { - return {std::tuple{std::forward(x), std::forward(y)}}; + return {{std::forward(x), std::forward(y)}}; } /** @@ -818,7 +818,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t atan2(X x, Y y) { - return {std::tuple{std::forward(x), std::forward(y)}}; + return {{std::forward(x), std::forward(y)}}; } /** @@ -830,7 +830,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t atanh(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -846,7 +846,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t atanh(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -858,7 +858,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t ceil(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -874,7 +874,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t ceil(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -886,7 +886,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t ceiling(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -902,7 +902,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t ceiling(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -914,7 +914,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t cos(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -930,7 +930,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t cos(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -942,7 +942,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t cosh(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -958,7 +958,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t cosh(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -970,7 +970,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t degrees(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -986,7 +986,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t degrees(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -998,7 +998,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t exp(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -1014,7 +1014,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t exp(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -1026,7 +1026,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t floor(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -1042,7 +1042,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t floor(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -1054,7 +1054,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t ln(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -1070,7 +1070,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t ln(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -1082,7 +1082,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t log(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -1098,7 +1098,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t log(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -1110,7 +1110,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t log10(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -1126,7 +1126,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t log10(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -1138,7 +1138,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t log(B b, X x) { - return {std::tuple{std::forward(b), std::forward(x)}}; + return {{std::forward(b), std::forward(x)}}; } /** @@ -1154,7 +1154,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t log(B b, X x) { - return {std::tuple{std::forward(b), std::forward(x)}}; + return {{std::forward(b), std::forward(x)}}; } /** @@ -1166,7 +1166,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t log2(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -1182,7 +1182,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t log2(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -1194,7 +1194,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t mod_f(X x, Y y) { - return {std::tuple{std::forward(x), std::forward(y)}}; + return {{std::forward(x), std::forward(y)}}; } /** @@ -1210,7 +1210,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t mod_f(X x, Y y) { - return {std::tuple{std::forward(x), std::forward(y)}}; + return {{std::forward(x), std::forward(y)}}; } /** @@ -1249,7 +1249,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t pow(X x, Y y) { - return {std::tuple{std::forward(x), std::forward(y)}}; + return {{std::forward(x), std::forward(y)}}; } /** @@ -1265,7 +1265,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t pow(X x, Y y) { - return {std::tuple{std::forward(x), std::forward(y)}}; + return {{std::forward(x), std::forward(y)}}; } /** @@ -1277,7 +1277,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t power(X x, Y y) { - return {std::tuple{std::forward(x), std::forward(y)}}; + return {{std::forward(x), std::forward(y)}}; } /** @@ -1293,7 +1293,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t power(X x, Y y) { - return {std::tuple{std::forward(x), std::forward(y)}}; + return {{std::forward(x), std::forward(y)}}; } /** @@ -1305,7 +1305,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t radians(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -1321,7 +1321,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t radians(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -1333,7 +1333,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t sin(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -1349,7 +1349,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t sin(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -1361,7 +1361,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t sinh(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -1377,7 +1377,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t sinh(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -1389,7 +1389,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t sqrt(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -1405,7 +1405,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t sqrt(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -1417,7 +1417,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t tan(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -1433,7 +1433,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t tan(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -1445,7 +1445,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t tanh(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -1461,7 +1461,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t tanh(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -1473,7 +1473,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t trunc(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -1489,7 +1489,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t trunc(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } #endif // SQLITE_ENABLE_MATH_FUNCTIONS /** @@ -1497,7 +1497,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t typeof_(T t) { - return {std::tuple{std::forward(t)}}; + return {{std::forward(t)}}; } /** @@ -1505,7 +1505,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t unicode(T t) { - return {std::tuple{std::forward(t)}}; + return {{std::forward(t)}}; } /** @@ -1513,7 +1513,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t length(T t) { - return {std::tuple{std::forward(t)}}; + return {{std::forward(t)}}; } /** @@ -1521,7 +1521,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t, internal::abs_string, T> abs(T t) { - return {std::tuple{std::forward(t)}}; + return {{std::forward(t)}}; } /** @@ -1529,7 +1529,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t lower(T t) { - return {std::tuple{std::forward(t)}}; + return {{std::forward(t)}}; } /** @@ -1537,7 +1537,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t upper(T t) { - return {std::tuple{std::forward(t)}}; + return {{std::forward(t)}}; } /** @@ -1566,7 +1566,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t trim(T t) { - return {std::tuple{std::forward(t)}}; + return {{std::forward(t)}}; } /** @@ -1574,7 +1574,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t trim(X x, Y y) { - return {std::tuple{std::forward(x), std::forward(y)}}; + return {{std::forward(x), std::forward(y)}}; } /** @@ -1582,7 +1582,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t ltrim(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -1590,7 +1590,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t ltrim(X x, Y y) { - return {std::tuple{std::forward(x), std::forward(y)}}; + return {{std::forward(x), std::forward(y)}}; } /** @@ -1598,7 +1598,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t rtrim(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -1606,7 +1606,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t rtrim(X x, Y y) { - return {std::tuple{std::forward(x), std::forward(y)}}; + return {{std::forward(x), std::forward(y)}}; } /** @@ -1614,7 +1614,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t hex(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -1622,7 +1622,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t quote(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -1630,7 +1630,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t, internal::randomblob_string, X> randomblob(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -1638,7 +1638,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t instr(X x, Y y) { - return {std::tuple{std::forward(x), std::forward(y)}}; + return {{std::forward(x), std::forward(y)}}; } /** @@ -1647,9 +1647,9 @@ namespace sqlite_orm { template, internal::is_into>::value == 0, bool> = true> + std::enable_if_t, internal::is_into>::value == 0, bool> = true> internal::built_in_function_t replace(X x, Y y, Z z) { - return {std::tuple{std::forward(x), std::forward(y), std::forward(z)}}; + return {{std::forward(x), std::forward(y), std::forward(z)}}; } /** @@ -1657,7 +1657,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t round(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -1665,7 +1665,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t round(X x, Y y) { - return {std::tuple{std::forward(x), std::forward(y)}}; + return {{std::forward(x), std::forward(y)}}; } #if SQLITE_VERSION_NUMBER >= 3007016 @@ -1675,7 +1675,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t char_(Args... args) { - return {std::make_tuple(std::forward(args)...)}; + return {{std::forward(args)...}}; } /** @@ -1698,7 +1698,7 @@ namespace sqlite_orm { polyfill::type_identity>::type, internal::coalesce_string, Args...> { - return {std::make_tuple(std::forward(args)...)}; + return {{std::forward(args)...}}; } /** @@ -1713,7 +1713,7 @@ namespace sqlite_orm { internal::ifnull_string, X, Y> { - return {std::make_tuple(std::move(x), std::move(y))}; + return {{std::move(x), std::move(y)}}; } /** @@ -1739,17 +1739,17 @@ namespace sqlite_orm { X, Y>; - return F{std::make_tuple(std::move(x), std::move(y))}; + return F{{std::move(x), std::move(y)}}; } else { using F = internal::built_in_function_t; - return F{std::make_tuple(std::move(x), std::move(y))}; + return F{{std::move(x), std::move(y)}}; } } #else template internal::built_in_function_t nullif(X x, Y y) { - return {std::make_tuple(std::move(x), std::move(y))}; + return {{std::move(x), std::move(y)}}; } #endif @@ -1758,7 +1758,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t date(Args... args) { - return {std::tuple{std::forward(args)...}}; + return {{std::forward(args)...}}; } /** @@ -1766,7 +1766,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t time(Args... args) { - return {std::tuple{std::forward(args)...}}; + return {{std::forward(args)...}}; } /** @@ -1774,7 +1774,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t datetime(Args... args) { - return {std::tuple{std::forward(args)...}}; + return {{std::forward(args)...}}; } /** @@ -1782,7 +1782,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t julianday(Args... args) { - return {std::tuple{std::forward(args)...}}; + return {{std::forward(args)...}}; } /** @@ -1790,7 +1790,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t strftime(Args... args) { - return {std::tuple{std::forward(args)...}}; + return {{std::forward(args)...}}; } /** @@ -1798,7 +1798,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t, internal::zeroblob_string, N> zeroblob(N n) { - return {std::tuple{std::forward(n)}}; + return {{std::forward(n)}}; } /** @@ -1806,7 +1806,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t substr(X x, Y y) { - return {std::tuple{std::forward(x), std::forward(y)}}; + return {{std::forward(x), std::forward(y)}}; } /** @@ -1814,7 +1814,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t substr(X x, Y y, Z z) { - return {std::tuple{std::forward(x), std::forward(y), std::forward(z)}}; + return {{std::forward(x), std::forward(y), std::forward(z)}}; } #ifdef SQLITE_SOUNDEX @@ -1823,7 +1823,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t soundex(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } #endif @@ -1832,7 +1832,7 @@ namespace sqlite_orm { */ template internal::built_in_aggregate_function_t total(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -1840,7 +1840,7 @@ namespace sqlite_orm { */ template internal::built_in_aggregate_function_t, internal::sum_string, X> sum(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -1848,7 +1848,7 @@ namespace sqlite_orm { */ template internal::built_in_aggregate_function_t count(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -1872,7 +1872,7 @@ namespace sqlite_orm { */ template internal::built_in_aggregate_function_t avg(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -1880,7 +1880,7 @@ namespace sqlite_orm { */ template internal::built_in_aggregate_function_t, internal::max_string, X> max(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -1888,7 +1888,7 @@ namespace sqlite_orm { */ template internal::built_in_aggregate_function_t, internal::min_string, X> min(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -1898,7 +1898,7 @@ namespace sqlite_orm { template internal::built_in_function_t, internal::max_string, X, Y, Rest...> max(X x, Y y, Rest... rest) { - return {std::tuple{std::forward(x), std::forward(y), std::forward(rest)...}}; + return {{std::forward(x), std::forward(y), std::forward(rest)...}}; } /** @@ -1908,7 +1908,7 @@ namespace sqlite_orm { template internal::built_in_function_t, internal::min_string, X, Y, Rest...> min(X x, Y y, Rest... rest) { - return {std::tuple{std::forward(x), std::forward(y), std::forward(rest)...}}; + return {{std::forward(x), std::forward(y), std::forward(rest)...}}; } /** @@ -1916,7 +1916,7 @@ namespace sqlite_orm { */ template internal::built_in_aggregate_function_t group_concat(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -1924,128 +1924,124 @@ namespace sqlite_orm { */ template internal::built_in_aggregate_function_t group_concat(X x, Y y) { - return {std::tuple{std::forward(x), std::forward(y)}}; + return {{std::forward(x), std::forward(y)}}; } #ifdef SQLITE_ENABLE_JSON1 template internal::built_in_function_t json(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } template internal::built_in_function_t json_array(Args... args) { - return {std::tuple{std::forward(args)...}}; + return {{std::forward(args)...}}; } template internal::built_in_function_t json_array_length(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } template internal::built_in_function_t json_array_length(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } template internal::built_in_function_t json_array_length(X x, Y y) { - return {std::tuple{std::forward(x), std::forward(y)}}; + return {{std::forward(x), std::forward(y)}}; } template internal::built_in_function_t json_array_length(X x, Y y) { - return {std::tuple{std::forward(x), std::forward(y)}}; + return {{std::forward(x), std::forward(y)}}; } template internal::built_in_function_t json_extract(X x, Args... args) { - return {std::tuple{std::forward(x), std::forward(args)...}}; + return {{std::forward(x), std::forward(args)...}}; } template internal::built_in_function_t json_insert(X x, Args... args) { - static_assert(std::tuple_size>::value % 2 == 0, - "number of arguments in json_insert must be odd"); - return {std::tuple{std::forward(x), std::forward(args)...}}; + static_assert(sizeof...(Args) % 2 == 0, "number of arguments in json_insert must be odd"); + return {{std::forward(x), std::forward(args)...}}; } template internal::built_in_function_t json_replace(X x, Args... args) { - static_assert(std::tuple_size>::value % 2 == 0, - "number of arguments in json_replace must be odd"); - return {std::tuple{std::forward(x), std::forward(args)...}}; + static_assert(sizeof...(Args) % 2 == 0, "number of arguments in json_replace must be odd"); + return {{std::forward(x), std::forward(args)...}}; } template internal::built_in_function_t json_set(X x, Args... args) { - static_assert(std::tuple_size>::value % 2 == 0, - "number of arguments in json_set must be odd"); - return {std::tuple{std::forward(x), std::forward(args)...}}; + static_assert(sizeof...(Args) % 2 == 0, "number of arguments in json_set must be odd"); + return {{std::forward(x), std::forward(args)...}}; } template internal::built_in_function_t json_object(Args... args) { - static_assert(std::tuple_size>::value % 2 == 0, - "number of arguments in json_object must be even"); - return {std::tuple{std::forward(args)...}}; + static_assert(sizeof...(Args) % 2 == 0, "number of arguments in json_object must be even"); + return {{std::forward(args)...}}; } template internal::built_in_function_t json_patch(X x, Y y) { - return {std::tuple{std::forward(x), std::forward(y)}}; + return {{std::forward(x), std::forward(y)}}; } template internal::built_in_function_t json_remove(X x, Args... args) { - return {std::tuple{std::forward(x), std::forward(args)...}}; + return {{std::forward(x), std::forward(args)...}}; } template internal::built_in_function_t json_remove(X x, Args... args) { - return {std::tuple{std::forward(x), std::forward(args)...}}; + return {{std::forward(x), std::forward(args)...}}; } template internal::built_in_function_t json_type(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } template internal::built_in_function_t json_type(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } template internal::built_in_function_t json_type(X x, Y y) { - return {std::tuple{std::forward(x), std::forward(y)}}; + return {{std::forward(x), std::forward(y)}}; } template internal::built_in_function_t json_type(X x, Y y) { - return {std::tuple{std::forward(x), std::forward(y)}}; + return {{std::forward(x), std::forward(y)}}; } template internal::built_in_function_t json_valid(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } template internal::built_in_function_t json_quote(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } template internal::built_in_function_t json_group_array(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } template internal::built_in_function_t json_group_object(X x, Y y) { - return {std::tuple{std::forward(x), std::forward(y)}}; + return {{std::forward(x), std::forward(y)}}; } #endif // SQLITE_ENABLE_JSON1 diff --git a/dev/expression.h b/dev/expression.h index b92fb0030..5c0fe105b 100644 --- a/dev/expression.h +++ b/dev/expression.h @@ -5,6 +5,7 @@ #include "functional/cxx_optional.h" #include "functional/cxx_universal.h" +#include "functional/tuple.h" // make_tuple #include "operators.h" namespace sqlite_orm { @@ -41,12 +42,12 @@ namespace sqlite_orm { #endif template in_t in(Args... args) const { - return {this->value, std::make_tuple(std::forward(args)...), false}; + return {this->value, mpl::make_tuple(std::forward(args)...), false}; } template in_t not_in(Args... args) const { - return {this->value, std::make_tuple(std::forward(args)...), true}; + return {this->value, mpl::make_tuple(std::forward(args)...), true}; } template diff --git a/dev/function.h b/dev/function.h index b1f62b50a..a6c2452ad 100644 --- a/dev/function.h +++ b/dev/function.h @@ -3,13 +3,14 @@ #include #include #include // std::string -#include // std::tuple #include // std::function #include // std::min #include // std::move, std::forward #include "functional/cxx_universal.h" #include "functional/cxx_type_traits_polyfill.h" +#include "functional/type_at.h" +#include "functional/tuple.h" namespace sqlite_orm { @@ -100,14 +101,14 @@ namespace sqlite_orm { template struct member_function_arguments { using member_function_type = R (O::*)(Args...) const; - using tuple_type = std::tuple...>; + using tuple_type = mpl::tuple...>; using return_type = R; }; template struct member_function_arguments { using member_function_type = R (O::*)(Args...); - using tuple_type = std::tuple...>; + using tuple_type = mpl::tuple...>; using return_type = R; }; @@ -132,7 +133,7 @@ namespace sqlite_orm { template struct function_call { using function_type = F; - using args_tuple = std::tuple; + using args_tuple = mpl::tuple; args_tuple args; }; @@ -203,13 +204,13 @@ namespace sqlite_orm { } template SQLITE_ORM_CONSTEVAL bool validate_pointer_value_types(polyfill::index_constant) { - using func_arg_t = std::tuple_element_t; - using passed_arg_t = unpacked_arg_t>; + using func_arg_t = mpl::element_at_t; + using passed_arg_t = unpacked_arg_t>; #ifdef SQLITE_ORM_RELAXED_CONSTEXPR_SUPPORTED constexpr bool valid = validate_pointer_value_type, - unpacked_arg_t>>( + mpl::element_at_t, + unpacked_arg_t>>( polyfill::bool_constant < (polyfill::is_specialization_of_v) || (polyfill::is_specialization_of_v) > {}); @@ -217,8 +218,8 @@ namespace sqlite_orm { #else return validate_pointer_value_types(polyfill::index_constant{}) && validate_pointer_value_type, - unpacked_arg_t>>( + mpl::element_at_t, + unpacked_arg_t>>( polyfill::bool_constant < (polyfill::is_specialization_of_v) || (polyfill::is_specialization_of_v) > {}); #endif @@ -230,17 +231,18 @@ namespace sqlite_orm { */ template internal::function_call func(Args... args) { - using args_tuple = std::tuple; - using function_args_tuple = typename internal::callable_arguments::args_tuple; - constexpr auto argsCount = std::tuple_size::value; + using namespace internal; + using args_pack = mpl::pack; + using function_args_tuple = typename callable_arguments::args_tuple; + constexpr auto argsCount = args_pack::size(); constexpr auto functionArgsCount = std::tuple_size::value; static_assert((argsCount == functionArgsCount && - !std::is_same>::value && - internal::validate_pointer_value_types( + !std::is_same>::value && + internal::validate_pointer_value_types, args_pack>( polyfill::index_constant(functionArgsCount, argsCount) - 1>{})) || - std::is_same>::value, + std::is_same>::value, "Number of arguments does not match"); - return {std::make_tuple(std::forward(args)...)}; + return {mpl::make_tuple(std::forward(args)...)}; } } diff --git a/dev/functional/cxx_compiler_quirks.h b/dev/functional/cxx_compiler_quirks.h index ab84d2980..6ba5d75ea 100644 --- a/dev/functional/cxx_compiler_quirks.h +++ b/dev/functional/cxx_compiler_quirks.h @@ -25,6 +25,33 @@ // Because we know what we are doing, we suppress the diagnostic message #define SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES(...) SQLITE_ORM_CLANG_SUPPRESS("-Wmissing-braces", __VA_ARGS__) -#if defined(_MSC_VER) && (_MSC_VER < 1920) +#if defined(_MSC_VER) && !defined(__clang__) // MSVC +#define SQLITE_ORM_MSVC_EMPTYBASES __declspec(empty_bases) +#else +#define SQLITE_ORM_MSVC_EMPTYBASES +#endif + +#if defined(_MSC_VER) && !defined(__clang__) // MSVC + +#if __cplusplus < 202002L +#define SQLITE_ORM_WORKAROUND_MSVC_MULTIPLECTOR_106654 +#endif + +#if _MSC_VER < 1920 #define SQLITE_ORM_BROKEN_VARIADIC_PACK_EXPANSION +#define SQLITE_ORM_BROKEN_CONSTEXPR_DELEGATING_CTORS +#endif + +#elif defined(__clang__) && defined(_MSC_VER) // Clang-cl (Clang for Windows) + +#elif defined(__clang__) && defined(__apple_build_version__) // Apple's Clang + +#elif defined(__clang__) // genuine Clang + +#elif defined(__GNUC__) // GCC + +#if __GNUC__ < 11 || (__GNUC__ == 11 && __GNUC_MINOR__ < 3) +#define SQLITE_ORM_BROKEN_GCC_ALIAS_TARGS_84785 +#endif + #endif diff --git a/dev/functional/cxx_core_features.h b/dev/functional/cxx_core_features.h index a1679fd40..68bbc3e0c 100644 --- a/dev/functional/cxx_core_features.h +++ b/dev/functional/cxx_core_features.h @@ -12,12 +12,22 @@ #define SQLITE_ORM_HAS_INCLUDE(file) 0L #endif +// If possible, use an intrinsic provided by Clang +#if defined(__has_builtin) +#if __has_builtin(__type_pack_element) +#define SQLITE_ORM_HAS_TYPE_PACK_ELEMENT_INTRINSIC +#endif +#endif + #if __cpp_aggregate_nsdmi >= 201304L #define SQLITE_ORM_AGGREGATE_NSDMI_SUPPORTED #endif #if __cpp_constexpr >= 201304L #define SQLITE_ORM_RELAXED_CONSTEXPR_SUPPORTED +#define SQLITE_ORM_NONCONST_CONSTEXPR constexpr +#else +#define SQLITE_ORM_NONCONST_CONSTEXPR #endif #if __cpp_noexcept_function_type >= 201510L @@ -57,6 +67,10 @@ #define SQLITE_ORM_NOUNIQUEADDRESS #endif +#if __cpp_conditional_explicit >= 201806L +#define SQLITE_ORM_CONDITIONAL_EXPLICIT_SUPPORTED +#endif + #if __cpp_consteval >= 201811L #define SQLITE_ORM_CONSTEVAL consteval #else diff --git a/dev/functional/cxx_type_traits_polyfill.h b/dev/functional/cxx_type_traits_polyfill.h index 7c19451c5..996684220 100644 --- a/dev/functional/cxx_type_traits_polyfill.h +++ b/dev/functional/cxx_type_traits_polyfill.h @@ -74,6 +74,30 @@ namespace sqlite_orm { using type_identity_t = typename type_identity::type; #endif +#if __cpp_lib_unwrap_ref >= 201811L + using std::unwrap_ref_decay, std::unwrap_ref_decay_t; + using std::unwrap_reference, std::unwrap_reference_t; +#else + template + struct unwrap_reference { + using type = T; + }; + template + struct unwrap_reference> { + using type = T&; + }; + template + using unwrap_reference_t = typename unwrap_reference::type; + + template + using unwrap_ref_decay_t = unwrap_reference_t>; + + template + struct unwrap_ref_decay { + using type = unwrap_ref_decay_t; + }; +#endif + #if 0 // __cpp_lib_detect >= 0L // library fundamentals TS v2, [meta.detect] using std::nonesuch; using std::detector; diff --git a/dev/functional/fast_and.h b/dev/functional/fast_and.h new file mode 100644 index 000000000..750f368f6 --- /dev/null +++ b/dev/functional/fast_and.h @@ -0,0 +1,22 @@ +#pragma once + +#include "cxx_universal.h" +#ifndef SQLITE_ORM_BROKEN_VARIADIC_PACK_EXPANSION +#include +#else +#include "cxx_type_traits_polyfill.h" +#endif + +#ifndef SQLITE_ORM_BROKEN_VARIADIC_PACK_EXPANSION +namespace sqlite_orm { + namespace internal { + + template + struct fast_and : std::is_same, fast_and<(v, true)...>> {}; + } +} + +#define SQLITE_ORM_FAST_AND(...) ::sqlite_orm::internal::fast_and<__VA_ARGS__::value...>::value +#else +#define SQLITE_ORM_FAST_AND(...) polyfill::conjunction<__VA_ARGS__...>::value +#endif diff --git a/dev/functional/index_sequence_util.h b/dev/functional/index_sequence_util.h new file mode 100644 index 000000000..017990bf7 --- /dev/null +++ b/dev/functional/index_sequence_util.h @@ -0,0 +1,116 @@ +#pragma once + +#include // std::integral_constant, std::declval +#include // std::index_sequence, std::make_index_sequence + +#include "cxx_universal.h" +#ifdef SQLITE_ORM_RELAXED_CONSTEXPR_SUPPORTED +#include +#endif +#include "pack.h" + +namespace sqlite_orm { + namespace internal { + namespace mpl { + /** + * Get the first value of an index_sequence. + */ + template + SQLITE_ORM_CONSTEVAL size_t first_index_sequence_value(std::index_sequence) { + return I; + } + +#ifdef SQLITE_ORM_RELAXED_CONSTEXPR_SUPPORTED + /** + * Reorder the values of an index_sequence according to the positions from a second sequence. + */ + template + SQLITE_ORM_CONSTEVAL auto reorder_index_sequence(std::index_sequence, + std::index_sequence) { + constexpr std::array values{Value...}; + return std::index_sequence{}; + } + + template + SQLITE_ORM_CONSTEVAL std::index_sequence reorder_index_sequence(std::index_sequence, + std::index_sequence) { + return {}; + } + + inline SQLITE_ORM_CONSTEVAL std::index_sequence<> reorder_index_sequence(std::index_sequence<>, + std::index_sequence<>) { + return {}; + } + + /** + * Reverse the values of an index_sequence. + */ + template + SQLITE_ORM_CONSTEVAL auto reverse_index_sequence(std::index_sequence) { + return reorder_index_sequence(std::index_sequence{}, std::make_index_sequence{}); + } +#endif + +#ifdef SQLITE_ORM_BROKEN_VARIADIC_PACK_EXPANSION + template + using comma_expression_helper = std::integral_constant; +#endif + + /* + * Duplicate specified number x times into an index sequence (using the size of the variadic argument x) + */ + template + constexpr auto expand_n(std::index_sequence) { +#ifndef SQLITE_ORM_BROKEN_VARIADIC_PACK_EXPANSION + using type = std::index_sequence<(x, n)...>; +#else + using type = std::index_sequence::value...>; +#endif + return type{}; + } + + template + using expand_n_t = decltype(expand_n(Times{})); + +#if defined(SQLITE_ORM_BROKEN_VARIADIC_PACK_EXPANSION) || defined(SQLITE_ORM_BROKEN_GCC_ALIAS_TARGS_84785) + template + struct spread_idxseq_helper { + using type = expand_n_t>; + }; +#endif + + template + constexpr auto spread_idxseq(std::index_sequence, std::index_sequence) { +#if !defined(SQLITE_ORM_BROKEN_VARIADIC_PACK_EXPANSION) && !defined(SQLITE_ORM_BROKEN_GCC_ALIAS_TARGS_84785) + using type = pack>...>; +#else + using type = pack::type...>; +#endif + return type{}; + } + + template + using spread_idxseq_t = decltype(spread_idxseq(std::declval(), std::declval())); + + template + struct flatten_idxseq { + using type = std::index_sequence<>; + }; + + template + struct flatten_idxseq> { + using type = std::index_sequence; + }; + + template + struct flatten_idxseq, std::index_sequence, Seq...> + : flatten_idxseq, Seq...> {}; + + template + struct flatten_idxseq> : flatten_idxseq {}; + + template + using flatten_idxseq_t = typename flatten_idxseq::type; + } + } +} diff --git a/dev/functional/indexed_type.h b/dev/functional/indexed_type.h new file mode 100644 index 000000000..c61701431 --- /dev/null +++ b/dev/functional/indexed_type.h @@ -0,0 +1,23 @@ +#pragma once + +#include "cxx_universal.h" + +namespace _sqlite_orm { + // short names defined in a short namespace to reduce symbol lengths, + // since those types are used as a building block; + // (as seen in boost hana) + + template + struct indexed_type { + using type = T; + }; +} + +namespace sqlite_orm { + namespace internal { + namespace mpl { + + using _sqlite_orm::indexed_type; + } + } +} diff --git a/dev/functional/pack.h b/dev/functional/pack.h new file mode 100644 index 000000000..37a3d6cd2 --- /dev/null +++ b/dev/functional/pack.h @@ -0,0 +1,33 @@ +#pragma once + +#include // std::integral_constant + +#include "cxx_universal.h" + +namespace sqlite_orm { + namespace internal { + namespace mpl { + + /* + * Type list + */ + template + struct pack { + static constexpr size_t size() { + return sizeof...(T); + } + }; + } + } + + namespace mpl = internal::mpl; +} + +// retain stl tuple interface for `pack` +namespace std { + template + struct tuple_size; + + template + struct tuple_size> : integral_constant {}; +} diff --git a/dev/functional/pack_util.h b/dev/functional/pack_util.h new file mode 100644 index 000000000..a429e73a2 --- /dev/null +++ b/dev/functional/pack_util.h @@ -0,0 +1,53 @@ +#pragma once + +#include "pack.h" +#include "mpl.h" + +namespace sqlite_orm { + namespace internal { + namespace mpl { + + /* + * Flatten specified type lists into specified result type list + */ + template class R, class... List> + struct flatten_types { + using type = R<>; + }; + + template class R, template class List1, class... X> + struct flatten_types> { + using type = R; + }; + + template class R, + template + class List1, + template + class List2, + class... X, + class... Y, + class... List> + struct flatten_types, List2, List...> : flatten_types, List...> {}; + + template class R, class... List> + using flatten_types_t = typename flatten_types::type; + + template class R, class List, template class Op> + struct transform_types; + + template class R, template class List, class... X, template class Op> + struct transform_types, Op> { + using type = R...>; + }; + + /* + * Transform specified type list. + * + * `Op` is a metafunction operation. + */ + template class R, class List, template class Op> + using transform_types_t = typename transform_types::type; + } + } +} diff --git a/dev/functional/tuple.h b/dev/functional/tuple.h new file mode 100644 index 000000000..58ee23470 --- /dev/null +++ b/dev/functional/tuple.h @@ -0,0 +1,382 @@ +#pragma once + +#include // std::integral_constant, std::decay, std::remove_reference, std::is_constructible, std::is_default_constructible, std::enable_if, std::declval +#include // std::move, std::forward +#include // std::equal_to + +#include "cxx_universal.h" +#include "cxx_type_traits_polyfill.h" +#include "fast_and.h" +#include "indexed_type.h" +#include "index_sequence_util.h" +#include "pack_util.h" +#include "type_at.h" +#include "tuple_common.h" + +namespace _sqlite_orm { + // short names defined in a short namespace to reduce symbol lengths, + // since those types are used as a building block; + // (as seen in boost hana) + + /* + * storage element of a tuple + */ + template::value && !std::is_final::value> + struct SQLITE_ORM_MSVC_EMPTYBASES tuplem : indexed_type { + X data; + + constexpr tuplem() : data() {} + + template + constexpr tuplem(Y&& y) : data(std::forward(y)) {} + }; + + /* + * storage element of a tuple, using EBO + */ + template + struct SQLITE_ORM_MSVC_EMPTYBASES tuplem : X, indexed_type { + + constexpr tuplem() = default; + + template + constexpr tuplem(Y&& y) : X(std::forward(y)) {} + }; + + template + constexpr const X& ebo_get(const tuplem& elem) { + return (elem.data); + } + template + constexpr X& ebo_get(tuplem& elem) { + return (elem.data); + } + template + constexpr X&& ebo_get(tuplem&& elem) { + return std::forward(elem.data); + } + template + constexpr const X& ebo_get(const tuplem& elem) { + return elem; + } + template + constexpr X& ebo_get(tuplem& elem) { + return elem; + } + template + constexpr X&& ebo_get(tuplem&& elem) { + return std::forward(elem); + } +} + +namespace sqlite_orm { + namespace internal { + namespace mpl { + using ::_sqlite_orm::ebo_get; + using ::_sqlite_orm::tuplem; + + template + struct basic_tuple; + + template + struct tuple; + + template + struct enable_tuple_ctor, Void...> + : std::enable_if), bool> {}; + + template + struct enable_tuple_ctor, Void...> + : std::enable_if), bool> {}; + + template + struct enable_tuple_variadic_ctor, Y...> + : std::enable_if), bool> {}; + +#ifdef SQLITE_ORM_WORKAROUND_MSVC_MULTIPLECTOR_106654 + template + struct enable_tuple_nonconst_copy_ctor, tuple, Void...> + : std::enable_if), bool> {}; + + template + struct enable_tuple_nonconst_copy_ctor, const tuple, Void...> + : std::enable_if), bool> {}; +#endif + } + } + + namespace mpl = internal::mpl; +} + +// retain stl tuple interface for `tuple` +namespace std { + template + struct tuple_size; + + template + struct tuple_element; + + template + struct tuple_size> : integral_constant {}; + + template + struct tuple_element> : sqlite_orm::mpl::type_at> { + }; + + template + constexpr decltype(auto) get(const sqlite_orm::mpl::tuple& tpl) noexcept { + using namespace sqlite_orm::mpl; + return ebo_get(tpl); + } + + template + constexpr decltype(auto) get(sqlite_orm::mpl::tuple& tpl) noexcept { + using namespace sqlite_orm::mpl; + return ebo_get(tpl); + } + + template + constexpr decltype(auto) get(sqlite_orm::mpl::tuple&& tpl) noexcept { + using namespace sqlite_orm::mpl; + return ebo_get(std::move(tpl)); + } + + template + decltype(auto) get(const sqlite_orm::mpl::tuple&) noexcept = delete; + + template + decltype(auto) get(sqlite_orm::mpl::tuple&) noexcept = delete; + + template + decltype(auto) get(sqlite_orm::mpl::tuple&&) noexcept = delete; +} + +namespace sqlite_orm { + namespace internal { + namespace mpl { + + template + struct SQLITE_ORM_MSVC_EMPTYBASES basic_tuple, X...> : tuplem... { + constexpr basic_tuple() = default; + + // variadic constructor + template + constexpr basic_tuple(from_variadic_t, Y&&... y) : tuplem(std::forward(y))... {} + + // converting copy/move constructor + template + constexpr basic_tuple(Other&& other) : tuplem(ebo_get(std::forward(other)))... {} + + // default copy constructor + constexpr basic_tuple(const basic_tuple&) = default; + // default move constructor + constexpr basic_tuple(basic_tuple&&) = default; + + // converting copy/move assignment + template + SQLITE_ORM_NONCONST_CONSTEXPR void operator=(Other&& other) { + int poormansfold[] = {(ebo_get(*this) = ebo_get(std::forward(other)), int{})...}; + (void)poormansfold; + } + + // default copy assignment + SQLITE_ORM_NONCONST_CONSTEXPR basic_tuple& operator=(const basic_tuple&) = default; + // default move assignment + SQLITE_ORM_NONCONST_CONSTEXPR basic_tuple& operator=(basic_tuple&&) = default; + }; + + template<> + struct tuple<> final { + constexpr tuple() = default; + }; + + /* + * tuple + */ + template + struct tuple final : basic_tuple, X...> { + using base_type = basic_tuple, X...>; + + // default constructor + template::type = true> + constexpr tuple() : base_type{} {} + + // direct constructor + template::type = true> + constexpr tuple(const X&... x) : base_type{from_variadic_t{}, x...} {} + + // converting constructor + template::type = true> + constexpr tuple(Y&&... y) : base_type{from_variadic_t{}, std::forward(y)...} {} + + // converting copy constructor + template), bool> = true> + constexpr tuple(const tuple& other) : base_type{other} {} + + // converting move constructor + template), bool> = true> + constexpr tuple(tuple&& other) : base_type{std::move(other)} {} + + // default copy constructor + constexpr tuple(const tuple&) = default; + // default move constructor + constexpr tuple(tuple&&) = default; + + // non-const copy constructor. + // The non-const copy constructor is required to make sure that + // the converting tuple(Y&&...) constructor is _not_ preferred over the copy + // constructor for unary tuples containing a type that is constructible from tuple<...>. +#ifndef SQLITE_ORM_WORKAROUND_MSVC_MULTIPLECTOR_106654 + constexpr tuple(tuple& other) : base_type{const_cast(other)} {} +#else + template::type = true> + constexpr tuple(Other& other) : base_type{const_cast(other)} {} +#endif + + // converting copy assignment + template), bool> = true> + SQLITE_ORM_NONCONST_CONSTEXPR tuple& operator=(const tuple& other) { + base_type::operator=(other); + return *this; + } + + // converting move assignment + template), bool> = true> + SQLITE_ORM_NONCONST_CONSTEXPR tuple& operator=(tuple&& other) { + base_type::operator=(std::move(other)); + return *this; + } + + // default copy assignment + SQLITE_ORM_NONCONST_CONSTEXPR tuple& operator=(const tuple&) = default; + // default move assignment + SQLITE_ORM_NONCONST_CONSTEXPR tuple& operator=(tuple&&) = default; + }; + + namespace adl { + template + constexpr auto make_tuple(X&&... x) { + return tuple...>{std::forward(x)...}; + } + + template + constexpr tuple forward_as_tuple(X&&... args) noexcept { + return {std::forward(args)...}; + } + + template + constexpr tuple tie(X&... args) noexcept { + return {args...}; + } + + template + constexpr flatten_types_t...> + tuple_cat_helper(std::index_sequence, std::index_sequence, Tuples&&... tuples) { + // Note that for each element in a tuple we have a coordinate pair (i, j), + // that is, the length of the lists containing the Is and the Js must be equal: + static_assert(sizeof...(Ix) == sizeof...(Jx), ""); + // It then explodes the tuple of tuples into the return type using the coordinates (i, j) for each element: + return {ebo_get(std::get(adl::forward_as_tuple(std::forward(tuples)...)))...}; + } + + /* + * This implementation of `tuple_cat` takes advantage of treating the specified tuples and + * their elements as a two-dimensional array. + * In order for this to work, the number of all elements combined (Jx) has to match + * a sequence of numbers produced using the number of specified tuples (Ix). + * Hence, each index in the sequence of tuples is duplicated by the number of elements of each respective tuple. + * + * Example, using 3 tuples: + * tuple0 + * tuple1 + * tuple0 + * + * outer sequence Jx (denoting which element to access): + * for tuple0: <0, 1, 2> + * for tuple1: <0> + * for tuple2: <0, 1> + * flattened -> <0, 1, 2, 0, 0, 1> + * + * inner sequence Ix (denoting which tuple to access): + * tuples as index sequence: <0, 1, 2> + * sizes as number sequence: <3, 1, 2> + * for tuple0: <0, 0, 0> + * for tuple1: <1> + * for tuple2: <2, 2> + * flattened -> <0, 0, 0, 1, 2, 2> + */ + template + constexpr auto tuple_cat(Tuples&&... tuples) { + using tuples_seq = std::make_index_sequence; + using sizes_seq = std::index_sequence>::value...>; + using inner = flatten_idxseq_t>; + using outer = typename flatten_idxseq< +#ifndef SQLITE_ORM_BROKEN_VARIADIC_PACK_EXPANSION + std::make_index_sequence>::value>... +#else + typename make_idxseq_helper>::type... +#endif + >::type; + + return tuple_cat_helper(inner{}, outer{}, std::forward(tuples)...); + } + } + using adl::forward_as_tuple; + using adl::make_tuple; + using adl::tie; + using adl::tuple_cat; + } + } +} + +// ops +namespace sqlite_orm { + namespace internal { + namespace mpl { + + // implementation note: we could derive from `type_at` but leverage the fact that `tuple` is derived from `indexed_type` + template + struct type_at> { + // implementation note: we could use `get_indexed_type()`, but `ebo_get` is readily available. + using forwarded_t = decltype(ebo_get(std::declval>())); + using type = remove_rvalue_reference_t; + }; + +#ifdef SQLITE_ORM_FOLD_EXPRESSIONS_SUPPORTED + template + constexpr bool equal_indexable([[maybe_unused]] const tuple& left, + [[maybe_unused]] const tuple& right, + std::index_sequence) { + constexpr std::equal_to<> predicate = {}; + return (predicate(ebo_get(left), ebo_get(right)) && ...); + } +#else + template + constexpr bool equal_indexable(const tuple&, const tuple&, std::index_sequence<>) { + return true; + } + template + constexpr bool + equal_indexable(const tuple& left, const tuple& right, std::index_sequence) { + return std::equal_to<>{}(ebo_get(left), ebo_get(right)) && + equal_indexable(left, right, std::index_sequence{}); + } +#endif + + template + constexpr bool operator==(const tuple& left, const tuple& right) { + static_assert(sizeof...(X) == sizeof...(Y), "cannot compare tuples of different sizes"); + return equal_indexable(left, right, std::make_index_sequence{}); + } + + template + constexpr bool operator!=(const tuple& left, const tuple& right) { + static_assert(sizeof...(X) == sizeof...(Y), "cannot compare tuples of different sizes"); + return !equal_indexable(left, right, std::make_index_sequence{}); + } + } + } +} diff --git a/dev/functional/tuple_common.h b/dev/functional/tuple_common.h new file mode 100644 index 000000000..a966682d7 --- /dev/null +++ b/dev/functional/tuple_common.h @@ -0,0 +1,46 @@ +#pragma once +#include // std::is_empty, std::is_final + +namespace _sqlite_orm { + template + constexpr bool is_ebo_able_v = std::is_empty::value && !std::is_final::value; +} + +namespace sqlite_orm { + namespace internal { + namespace mpl { + using _sqlite_orm::is_ebo_able_v; + + template + struct enable_tuple_variadic_ctor; + + template + struct enable_tuple_ctor; + + template + struct enable_tuple_nonconst_copy_ctor; + + struct from_variadic_t {}; + + template + struct remove_rvalue_reference { + using type = T; + }; + template + struct remove_rvalue_reference { + using type = T; + }; + template + using remove_rvalue_reference_t = typename remove_rvalue_reference::type; + +#ifdef SQLITE_ORM_BROKEN_VARIADIC_PACK_EXPANSION + template + struct make_idxseq_helper { + using type = std::make_index_sequence::value>; + }; +#endif + } + } + + namespace mpl = internal::mpl; +} diff --git a/dev/functional/type_at.h b/dev/functional/type_at.h new file mode 100644 index 000000000..a72b7775a --- /dev/null +++ b/dev/functional/type_at.h @@ -0,0 +1,48 @@ +#pragma once + +#include // std::integral_constant, std::index_sequence, std::make_index_sequence + +#include "cxx_universal.h" +#include "indexed_type.h" +#include "pack.h" + +namespace sqlite_orm { + namespace internal { + namespace mpl { + +#ifndef SQLITE_ORM_HAS_TYPE_PACK_ELEMENT_INTRINSIC + template + struct indexer; + + template + struct indexer, T...> : indexed_type... {}; + + template + indexed_type get_indexed_type(const indexed_type&); +#endif + + template + struct type_at { +#ifdef SQLITE_ORM_HAS_TYPE_PACK_ELEMENT_INTRINSIC + using type = __type_pack_element; +#else + using Indexer = indexer, T...>; + // implementation note: needs to be aliased on its own [SQLITE_ORM_BROKEN_VARIADIC_PACK_EXPANSION] + using indexed_t = decltype(get_indexed_type(Indexer{})); + using type = typename indexed_t::type; +#endif + }; + + template + struct type_at> : type_at {}; + + template + using type_at_t = typename type_at::type; + + template + using element_at_t = typename type_at::type; + } + } + + namespace mpl = internal::mpl; +} diff --git a/dev/functional/unique_tuple.h b/dev/functional/unique_tuple.h new file mode 100644 index 000000000..01042b40e --- /dev/null +++ b/dev/functional/unique_tuple.h @@ -0,0 +1,301 @@ +#pragma once + +#include // std::integral_constant, std::decay, std::is_constructible, std::is_default_constructible, std::enable_if +#include // std::move, std::forward +#include // std::equal_to + +#include "cxx_universal.h" +#include "cxx_type_traits_polyfill.h" +#include "fast_and.h" +#include "type_at.h" +#include "tuple_common.h" + +namespace _sqlite_orm { + // short names defined in a short namespace to reduce symbol lengths, + // since those types are used as a building block; + // (as seen in boost hana) + + /* + * storage element of a unique tuple + */ + template> + struct uplem { + X data; + + constexpr uplem() : data() {} + + template + constexpr uplem(Y&& y) : data(std::forward(y)) {} + }; + + /* + * storage element of a unique tuple, using EBO + */ + template + struct uplem : X { + + constexpr uplem() = default; + + template + constexpr uplem(Y&& y) : X(std::forward(y)) {} + }; + + template>> + constexpr const X& ebo_get(const uplem& elem) { + return (elem.data); + } + template, bool> = true> + constexpr X& ebo_get(uplem& elem) { + return (elem.data); + } + template, bool> = true> + constexpr X&& ebo_get(uplem&& elem) { + return std::forward(elem.data); + } + template, bool> = true> + constexpr const X& ebo_get(const uplem& elem) { + return elem; + } + template, bool> = true> + constexpr X& ebo_get(uplem& elem) { + return elem; + } + template, bool> = true> + constexpr X&& ebo_get(uplem&& elem) { + return std::forward(elem); + } +} + +namespace sqlite_orm { + namespace internal { + namespace mpl { + using ::_sqlite_orm::ebo_get; + using ::_sqlite_orm::uplem; + + template + struct uple; + + template + struct enable_tuple_ctor, Void...> + : std::enable_if), bool> {}; + + template + struct enable_tuple_ctor, Void...> + : std::enable_if), bool> {}; + + template + struct enable_tuple_variadic_ctor, Y...> + : std::enable_if), bool> {}; + +#ifdef SQLITE_ORM_WORKAROUND_MSVC_MULTIPLECTOR_106654 + template + struct enable_tuple_nonconst_copy_ctor, uple, Void...> + : std::enable_if), bool> {}; + + template + struct enable_tuple_nonconst_copy_ctor, const uple, Void...> + : std::enable_if), bool> {}; +#endif + } + } + + namespace mpl = internal::mpl; +} + +// retain stl tuple interface for `uple` +namespace std { + template + struct tuple_size; + + template + struct tuple_element; + + template + struct tuple_size> : integral_constant {}; + + template + struct tuple_element> : sqlite_orm::mpl::type_at> {}; + + template + constexpr decltype(auto) get(const sqlite_orm::mpl::uple& tpl) noexcept { + using namespace sqlite_orm::mpl; + using type = type_at_t; + return ebo_get(static_cast&>(tpl)); + } + + template + constexpr decltype(auto) get(sqlite_orm::mpl::uple& tpl) noexcept { + using namespace sqlite_orm::mpl; + using type = type_at_t; + return ebo_get(static_cast&>(tpl)); + } + + template + constexpr decltype(auto) get(sqlite_orm::mpl::uple&& tpl) noexcept { + using namespace sqlite_orm::mpl; + using type = type_at_t; + return ebo_get(static_cast&&>(tpl)); + } + + template + constexpr decltype(auto) get(const sqlite_orm::mpl::uple& tpl) noexcept { + using namespace sqlite_orm::mpl; + return ebo_get(static_cast&>(tpl)); + } + + template + constexpr decltype(auto) get(sqlite_orm::mpl::uple& tpl) noexcept { + using namespace sqlite_orm::mpl; + return ebo_get(static_cast&>(tpl)); + } + + template + constexpr decltype(auto) get(sqlite_orm::mpl::uple&& tpl) noexcept { + using namespace sqlite_orm::mpl; + return ebo_get(static_cast&&>(tpl)); + } +} + +namespace sqlite_orm { + namespace internal { + namespace mpl { + + template<> + struct uple<> final { + constexpr uple() = default; + }; + + /* + * unique tuple, which allows only distinct types. + */ + template + struct SQLITE_ORM_MSVC_EMPTYBASES uple final : uplem... { + // default constructor + template::type = true> + constexpr uple() {} + + // direct constructor + template::type = true> + constexpr uple(const X&... x) : uplem(x)... {} + + // converting constructor + template::type = true> + constexpr uple(Y&&... y) : uplem(std::forward(y))... {} + + // converting copy constructor + template), bool> = true> + constexpr uple(const uple& other) : uplem(ebo_get(other))... {} + + // converting move constructor + template), bool> = true> + constexpr uple(uple&& other) : uplem(ebo_get(std::move(other)))... {} + + // default copy constructor + constexpr uple(const uple&) = default; + // default move constructor + constexpr uple(uple&&) = default; + + // non-const copy constructor. + // The non-const copy constructor is required to make sure that + // the converting uple(Y&&...) constructor is _not_ preferred over the copy + // constructor for unary tuples containing a type that is constructible from uple<...>. +#ifndef SQLITE_ORM_WORKAROUND_MSVC_MULTIPLECTOR_106654 + constexpr uple(uple& other) : uplem(ebo_get(const_cast(other)))... {} +#else + template::type = true> + constexpr uple(Other& other) : uplem(ebo_get(const_cast(other)))... {} +#endif + + // converting copy assignment + template), bool> = true> + SQLITE_ORM_NONCONST_CONSTEXPR uple& operator=(const uple& other) { + int poormansfold[] = {(ebo_get(*this) = ebo_get(other), int{})...}; + (void)poormansfold; + return *this; + } + + // converting move assignment + template), bool> = true> + SQLITE_ORM_NONCONST_CONSTEXPR uple& operator=(uple&& other) { + int poormansfold[] = {(ebo_get(*this) = ebo_get(std::move(other)), int{})...}; + (void)poormansfold; + return *this; + } + + // default copy assignment + SQLITE_ORM_NONCONST_CONSTEXPR uple& operator=(const uple&) = default; + // default move assignment + SQLITE_ORM_NONCONST_CONSTEXPR uple& operator=(uple&&) = default; + }; + + template + constexpr auto make_unique_tuple(X&&... x) { + return uple...>{std::forward(x)...}; + } + + template + constexpr uple forward_as_unique_tuple(X&&... args) noexcept { + return {std::forward(args)...}; + } + + template + constexpr uple tie_unique(X&... args) noexcept { + return {args...}; + } + } + } +} + +// ops +namespace sqlite_orm { + namespace internal { + namespace mpl { + + template + struct type_at> : type_at {}; + +#ifdef SQLITE_ORM_FOLD_EXPRESSIONS_SUPPORTED + template = true> + constexpr bool equal_indexable([[maybe_unused]] const uple& left, + [[maybe_unused]] const uple& right, + std::index_sequence) { + return ((ebo_get(left) == ebo_get(right)) && ...); + } + + template = true> + constexpr bool equal_indexable([[maybe_unused]] const uple& left, + [[maybe_unused]] const uple& right, + std::index_sequence) { + constexpr std::equal_to<> predicate = {}; + return (predicate(std::get(left), std::get(right)) && ...); + } +#else + template + constexpr bool equal_indexable(const uple&, const uple&, std::index_sequence<>) { + return true; + } + template + constexpr bool + equal_indexable(const uple& left, const uple& right, std::index_sequence) { + return std::equal_to<>{}(std::get(left), std::get(right)) && + equal_indexable(left, right, std::index_sequence{}); + } +#endif + + template + constexpr bool operator==(const uple& left, const uple& right) { + static_assert(sizeof...(X) == sizeof...(Y), "cannot compare tuples of different sizes"); + return equal_indexable(left, right, std::make_index_sequence{}); + } + + template + constexpr bool operator!=(const uple& left, const uple& right) { + static_assert(sizeof...(X) == sizeof...(Y), "cannot compare tuples of different sizes"); + return !equal_indexable(left, right, std::make_index_sequence{}); + } + } + } +} diff --git a/dev/get_prepared_statement.h b/dev/get_prepared_statement.h index fc30aefe4..6ab15e8a9 100644 --- a/dev/get_prepared_statement.h +++ b/dev/get_prepared_statement.h @@ -3,6 +3,8 @@ #include // std::is_same, std::decay, std::remove_reference #include "functional/static_magic.h" +#include "functional/cxx_type_traits_polyfill.h" +#include "functional/type_at.h" #include "prepared_statement.h" #include "ast_iterator.h" #include "expression_object_type.h" @@ -121,24 +123,24 @@ namespace sqlite_orm { template const auto& get(const internal::prepared_statement_t& statement) { - using statement_type = std::decay_t; + using statement_type = std::remove_reference_t; using expression_type = typename statement_type::expression_type; using node_tuple = internal::node_tuple_t; using bind_tuple = internal::bindable_filter_t; - using result_type = std::tuple_element_t(N), bind_tuple>; + using result_type = mpl::element_at_t(N), bind_tuple>; const result_type* result = nullptr; internal::iterate_ast(statement.expression, [&result, index = -1](auto& node) mutable { - using node_type = std::decay_t; + using node_type = polyfill::remove_cvref_t; if(internal::is_bindable_v) { ++index; - } - if(index == N) { - internal::call_if_constexpr::value>( - [](auto& r, auto& n) { - r = &n; - }, - result, - node); + if(index == N) { + internal::call_if_constexpr::value>( + [](auto& r, auto& n) { + r = &n; + }, + result, + node); + } } }); return internal::get_ref(*result); @@ -146,25 +148,25 @@ namespace sqlite_orm { template auto& get(internal::prepared_statement_t& statement) { - using statement_type = std::decay_t; + using statement_type = std::remove_reference_t; using expression_type = typename statement_type::expression_type; using node_tuple = internal::node_tuple_t; using bind_tuple = internal::bindable_filter_t; - using result_type = std::tuple_element_t(N), bind_tuple>; + using result_type = mpl::element_at_t(N), bind_tuple>; result_type* result = nullptr; internal::iterate_ast(statement.expression, [&result, index = -1](auto& node) mutable { - using node_type = std::decay_t; + using node_type = polyfill::remove_cvref_t; if(internal::is_bindable_v) { ++index; - } - if(index == N) { - internal::call_if_constexpr::value>( - [](auto& r, auto& n) { - r = const_cast>(&n); - }, - result, - node); + if(index == N) { + internal::call_if_constexpr::value>( + [](auto& r, auto& n) { + r = const_cast>(&n); + }, + result, + node); + } } }); return internal::get_ref(*result); diff --git a/dev/implementations/column_definitions.h b/dev/implementations/column_definitions.h index a637bd883..585cc3959 100644 --- a/dev/implementations/column_definitions.h +++ b/dev/implementations/column_definitions.h @@ -8,7 +8,7 @@ #include "../functional/cxx_core_features.h" #include "../functional/static_magic.h" -#include "../tuple_helper/index_sequence_util.h" +#include "../functional/index_sequence_util.h" #include "../tuple_helper/tuple_filter.h" #include "../tuple_helper/tuple_traits.h" #include "../default_value_extractor.h" @@ -26,8 +26,8 @@ namespace sqlite_orm { call_if_constexpr( [&value](auto& constraints, auto op_index_sequence) { using default_op_index_sequence = decltype(op_index_sequence); - constexpr size_t opIndex = first_index_sequence_value(default_op_index_sequence{}); - value = std::make_unique(serialize_default_value(get(constraints))); + constexpr size_t opIndex = mpl::first_index_sequence_value(default_op_index_sequence{}); + value = std::make_unique(serialize_default_value(std::get(constraints))); }, this->constraints, default_op_index_sequence{}); diff --git a/dev/implementations/table_definitions.h b/dev/implementations/table_definitions.h index 30a2dcabc..b53d619bf 100644 --- a/dev/implementations/table_definitions.h +++ b/dev/implementations/table_definitions.h @@ -3,7 +3,7 @@ * this file is also used to provide definitions of interface methods 'hitting the database'. */ #pragma once -#include // std::decay_t +#include // std::remove_reference #include // std::move #include // std::find_if, std::ranges::find @@ -19,7 +19,7 @@ namespace sqlite_orm { std::vector res; res.reserve(size_t(filter_tuple_sequence_t::size())); this->for_each_column([&res](auto& column) { - using field_type = field_type_t>; + using field_type = field_type_t>; std::string dft; if(auto d = column.default_value()) { dft = move(*d); diff --git a/dev/index.h b/dev/index.h index 36e25815d..c40f2bc1b 100644 --- a/dev/index.h +++ b/dev/index.h @@ -1,10 +1,11 @@ #pragma once -#include // std::tuple, std::make_tuple, std::declval +#include // std::declval #include // std::string #include // std::forward #include "functional/cxx_universal.h" +#include "functional/tuple.h" #include "tuple_helper/tuple_filter.h" #include "indexed_column.h" @@ -23,12 +24,12 @@ namespace sqlite_orm { template struct index_t : index_base { - using elements_type = std::tuple; + using elements_type = mpl::tuple; using object_type = void; #ifndef SQLITE_ORM_AGGREGATE_BASES_SUPPORTED index_t(std::string name_, bool unique_, elements_type elements_) : - index_base{move(name_), unique_}, elements(move(elements_)) {} + index_base{move(name_), unique_}, elements(std::move(elements_)) {} #endif elements_type elements; @@ -38,20 +39,18 @@ namespace sqlite_orm { template internal::index_t()))...> make_index(std::string name, Cols... cols) { - using cols_tuple = std::tuple; - static_assert(internal::count_tuple::value <= 1, + static_assert(internal::count_tuple, internal::is_where>::value <= 1, "amount of where arguments can be 0 or 1"); SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES( - return {move(name), false, std::make_tuple(internal::make_indexed_column(std::move(cols))...)}); + return {move(name), false, mpl::make_tuple(internal::make_indexed_column(std::move(cols))...)}); } template internal::index_t()))...> make_unique_index(std::string name, Cols... cols) { - using cols_tuple = std::tuple; - static_assert(internal::count_tuple::value <= 1, + static_assert(internal::count_tuple, internal::is_where>::value <= 1, "amount of where arguments can be 0 or 1"); SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES( - return {move(name), true, std::make_tuple(internal::make_indexed_column(std::move(cols))...)}); + return {move(name), true, mpl::make_tuple(internal::make_indexed_column(std::move(cols))...)}); } } diff --git a/dev/node_tuple.h b/dev/node_tuple.h index 4f10bdb52..e6ae56e69 100644 --- a/dev/node_tuple.h +++ b/dev/node_tuple.h @@ -5,6 +5,8 @@ #include // std::reference_wrapper #include "functional/cxx_optional.h" +#include "functional/type_at.h" +#include "functional/tuple.h" #include "tuple_helper/tuple_filter.h" #include "conditions.h" #include "operators.h" @@ -25,7 +27,7 @@ namespace sqlite_orm { template struct node_tuple { - using type = std::tuple; + using type = mpl::tuple; }; template @@ -33,7 +35,7 @@ namespace sqlite_orm { template<> struct node_tuple { - using type = std::tuple<>; + using type = mpl::tuple<>; }; #ifdef SQLITE_ORM_OPTIONAL_SUPPORTED template @@ -43,18 +45,18 @@ namespace sqlite_orm { struct node_tuple, void> : node_tuple {}; template - struct node_tuple, void> : node_tuple> {}; + struct node_tuple, void> : node_tuple> {}; template struct node_tuple, void> { - using args_tuple = node_tuple_t>; + using args_tuple = node_tuple_t>; using expression_tuple = node_tuple_t; using type = tuple_cat_t; }; template - struct node_tuple, std::tuple>, void> - : node_tuple> {}; + struct node_tuple, mpl::tuple>, void> + : node_tuple> {}; template struct node_tuple, void> { @@ -161,6 +163,11 @@ namespace sqlite_orm { using type = tuple_cat_t...>; }; + template + struct node_tuple, void> { + using type = tuple_cat_t...>; + }; + template struct node_tuple, void> { using type = tuple_cat_t...>; diff --git a/dev/pointer_value.h b/dev/pointer_value.h index 36d37cd25..f0bfaac3e 100644 --- a/dev/pointer_value.h +++ b/dev/pointer_value.h @@ -64,8 +64,7 @@ namespace sqlite_orm { class pointer_binding { P* p_; - SQLITE_ORM_NOUNIQUEADDRESS - D d_; + SQLITE_ORM_NOUNIQUEADDRESS D d_; protected: // Constructing pointer bindings must go through bindable_pointer() diff --git a/dev/prepared_statement.h b/dev/prepared_statement.h index b4091f4ef..e4a8c2fa6 100644 --- a/dev/prepared_statement.h +++ b/dev/prepared_statement.h @@ -4,12 +4,14 @@ #include // std::unique_ptr #include // std::iterator_traits #include // std::string -#include // std::integral_constant, std::declval +#include // std::integral_constant, std::declval, std::decay #include // std::pair #include "functional/cxx_universal.h" #include "functional/cxx_type_traits_polyfill.h" #include "functional/cxx_functional_polyfill.h" +#include "functional/pack.h" +#include "functional/tuple.h" #include "tuple_helper/tuple_filter.h" #include "connection_holder.h" #include "select_constraints.h" @@ -101,7 +103,7 @@ namespace sqlite_orm { using type = T; using return_type = R; - using conditions_type = std::tuple; + using conditions_type = mpl::tuple; conditions_type conditions; }; @@ -111,7 +113,7 @@ namespace sqlite_orm { using type = T; using return_type = R; - using conditions_type = std::tuple; + using conditions_type = mpl::tuple; conditions_type conditions; }; @@ -122,7 +124,7 @@ namespace sqlite_orm { using type = T; using return_type = R; - using conditions_type = std::tuple; + using conditions_type = mpl::tuple; conditions_type conditions; }; @@ -134,7 +136,7 @@ namespace sqlite_orm { template struct update_all_t, Wargs...> { using set_type = set_t; - using conditions_type = std::tuple; + using conditions_type = mpl::tuple; set_type set; conditions_type conditions; @@ -143,7 +145,7 @@ namespace sqlite_orm { template struct remove_all_t { using type = T; - using conditions_type = std::tuple; + using conditions_type = mpl::tuple; conditions_type conditions; }; @@ -151,7 +153,7 @@ namespace sqlite_orm { template struct get_t { using type = T; - using ids_type = std::tuple; + using ids_type = mpl::tuple; ids_type ids; }; @@ -159,7 +161,7 @@ namespace sqlite_orm { template struct get_pointer_t { using type = T; - using ids_type = std::tuple; + using ids_type = mpl::tuple; ids_type ids; }; @@ -168,7 +170,7 @@ namespace sqlite_orm { template struct get_optional_t { using type = T; - using ids_type = std::tuple; + using ids_type = mpl::tuple; ids_type ids; }; @@ -184,7 +186,7 @@ namespace sqlite_orm { template struct remove_t { using type = T; - using ids_type = std::tuple; + using ids_type = mpl::tuple; ids_type ids; }; @@ -258,7 +260,7 @@ namespace sqlite_orm { template struct insert_raw_t { - using args_tuple = std::tuple; + using args_tuple = mpl::tuple; args_tuple args; }; @@ -271,7 +273,7 @@ namespace sqlite_orm { template struct replace_raw_t { - using args_tuple = std::tuple; + using args_tuple = mpl::tuple; args_tuple args; }; @@ -378,7 +380,7 @@ namespace sqlite_orm { */ template internal::insert_raw_t insert(Args... args) { - using args_tuple = std::tuple; + using args_tuple = mpl::pack; using internal::count_tuple; using internal::is_columns; using internal::is_insert_constraint; @@ -450,7 +452,7 @@ namespace sqlite_orm { */ template internal::replace_raw_t replace(Args... args) { - using args_tuple = std::tuple; + using args_tuple = mpl::tuple; using internal::count_tuple; using internal::is_columns; using internal::is_into; @@ -592,8 +594,8 @@ namespace sqlite_orm { */ template internal::remove_t remove(Ids... ids) { - std::tuple idsTuple{std::forward(ids)...}; - return {move(idsTuple)}; + mpl::tuple idsTuple{std::forward(ids)...}; + return {std::move(idsTuple)}; } /** @@ -615,8 +617,7 @@ namespace sqlite_orm { */ template internal::get_t get(Ids... ids) { - std::tuple idsTuple{std::forward(ids)...}; - return {move(idsTuple)}; + return {mpl::make_tuple(std::forward(ids)...)}; } /** @@ -626,8 +627,7 @@ namespace sqlite_orm { */ template internal::get_pointer_t get_pointer(Ids... ids) { - std::tuple idsTuple{std::forward(ids)...}; - return {move(idsTuple)}; + return {mpl::make_tuple(std::forward(ids)...)}; } #ifdef SQLITE_ORM_OPTIONAL_SUPPORTED @@ -638,8 +638,7 @@ namespace sqlite_orm { */ template internal::get_optional_t get_optional(Ids... ids) { - std::tuple idsTuple{std::forward(ids)...}; - return {move(idsTuple)}; + return {mpl::make_tuple(std::forward(ids)...)}; } #endif // SQLITE_ORM_OPTIONAL_SUPPORTED @@ -650,10 +649,10 @@ namespace sqlite_orm { */ template internal::remove_all_t remove_all(Args... args) { - using args_tuple = std::tuple; + using args_tuple = mpl::tuple; internal::validate_conditions(); args_tuple conditions{std::forward(args)...}; - return {move(conditions)}; + return {std::move(conditions)}; } /** @@ -663,10 +662,10 @@ namespace sqlite_orm { */ template internal::get_all_t, Args...> get_all(Args... args) { - using args_tuple = std::tuple; + using args_tuple = mpl::tuple; internal::validate_conditions(); args_tuple conditions{std::forward(args)...}; - return {move(conditions)}; + return {std::move(conditions)}; } /** @@ -677,10 +676,10 @@ namespace sqlite_orm { */ template internal::get_all_t get_all(Args... args) { - using args_tuple = std::tuple; + using args_tuple = mpl::tuple; internal::validate_conditions(); args_tuple conditions{std::forward(args)...}; - return {move(conditions)}; + return {std::move(conditions)}; } /** @@ -689,10 +688,10 @@ namespace sqlite_orm { */ template internal::update_all_t, Wargs...> update_all(internal::set_t set, Wargs... wh) { - using args_tuple = std::tuple; + using args_tuple = mpl::tuple; internal::validate_conditions(); args_tuple conditions{std::forward(wh)...}; - return {std::move(set), move(conditions)}; + return {std::move(set), std::move(conditions)}; } /** @@ -702,10 +701,10 @@ namespace sqlite_orm { */ template internal::get_all_pointer_t>, Args...> get_all_pointer(Args... args) { - using args_tuple = std::tuple; + using args_tuple = mpl::tuple; internal::validate_conditions(); args_tuple conditions{std::forward(args)...}; - return {move(conditions)}; + return {std::move(conditions)}; } /** * Create a get all pointer statement. @@ -715,10 +714,10 @@ namespace sqlite_orm { */ template internal::get_all_pointer_t get_all_pointer(Args... args) { - using args_tuple = std::tuple; + using args_tuple = mpl::tuple; internal::validate_conditions(); args_tuple conditions{std::forward(args)...}; - return {move(conditions)}; + return {std::move(conditions)}; } #ifdef SQLITE_ORM_OPTIONAL_SUPPORTED @@ -729,10 +728,10 @@ namespace sqlite_orm { */ template internal::get_all_optional_t>, Args...> get_all_optional(Args... args) { - using args_tuple = std::tuple; + using args_tuple = mpl::tuple; internal::validate_conditions(); args_tuple conditions{std::forward(args)...}; - return {move(conditions)}; + return {std::move(conditions)}; } /** @@ -743,10 +742,10 @@ namespace sqlite_orm { */ template internal::get_all_optional_t get_all_optional(Args... args) { - using args_tuple = std::tuple; + using args_tuple = mpl::tuple; internal::validate_conditions(); args_tuple conditions{std::forward(args)...}; - return {move(conditions)}; + return {std::move(conditions)}; } #endif // SQLITE_ORM_OPTIONAL_SUPPORTED } diff --git a/dev/row_extractor.h b/dev/row_extractor.h index ed60e596a..f6e6759a3 100644 --- a/dev/row_extractor.h +++ b/dev/row_extractor.h @@ -13,7 +13,7 @@ #include #include // std::copy #include // std::back_inserter -#include // std::tuple, std::tuple_size, std::tuple_element +#include // std::tuple #include "functional/cxx_universal.h" #include "arithmetic_tag.h" diff --git a/dev/select_constraints.h b/dev/select_constraints.h index f16bcc98f..254f68d9a 100644 --- a/dev/select_constraints.h +++ b/dev/select_constraints.h @@ -7,6 +7,7 @@ #include "functional/cxx_universal.h" #include "functional/cxx_type_traits_polyfill.h" +#include "functional/tuple.h" #include "is_base_of_template.h" #include "tuple_helper/tuple_filter.h" #include "optional_container.h" @@ -62,7 +63,7 @@ namespace sqlite_orm { template struct columns_t { - using columns_type = std::tuple; + using columns_type = mpl::tuple; columns_type columns; bool distinct = false; @@ -70,7 +71,7 @@ namespace sqlite_orm { static constexpr int count = std::tuple_size::value; #ifndef SQLITE_ORM_AGGREGATE_NSDMI_SUPPORTED - columns_t(columns_type columns) : columns{move(columns)} {} + columns_t(columns_type columns) : columns{std::move(columns)} {} #endif }; @@ -82,7 +83,7 @@ namespace sqlite_orm { template struct set_t { - using assigns_type = std::tuple; + using assigns_type = mpl::tuple; assigns_type assigns; }; @@ -136,14 +137,15 @@ namespace sqlite_orm { template struct select_t { using return_type = T; - using conditions_type = std::tuple; + using conditions_type = mpl::tuple; return_type col; conditions_type conditions; bool highest_level = false; #ifndef SQLITE_ORM_AGGREGATE_NSDMI_SUPPORTED - select_t(return_type col, conditions_type conditions) : col{std::move(col)}, conditions{move(conditions)} {} + select_t(return_type col, conditions_type conditions) : + col{std::move(col)}, conditions{std::move(conditions)} {} #endif }; @@ -281,7 +283,7 @@ namespace sqlite_orm { struct simple_case_t { using return_type = R; using case_expression_type = T; - using args_type = std::tuple; + using args_type = mpl::tuple; using else_expression_type = E; optional_container case_expression; @@ -298,7 +300,7 @@ namespace sqlite_orm { struct simple_case_builder { using return_type = R; using case_expression_type = T; - using args_type = std::tuple; + using args_type = mpl::tuple; using else_expression_type = E; optional_container case_expression; @@ -307,9 +309,9 @@ namespace sqlite_orm { template simple_case_builder> when(W w, then_t t) { - using result_args_type = std::tuple>; + using result_args_type = mpl::tuple>; std::pair newPair{std::move(w), std::move(t.expression)}; - result_args_type result_args = std::tuple_cat(std::move(this->args), std::make_tuple(newPair)); + result_args_type result_args = mpl::tuple_cat(std::move(this->args), mpl::make_tuple(newPair)); std::get::value - 1>(result_args) = std::move(newPair); return {std::move(this->case_expression), std::move(result_args), std::move(this->else_expression)}; } @@ -377,16 +379,16 @@ namespace sqlite_orm { */ template internal::set_t set(Args... args) { - using arg_tuple = std::tuple; - static_assert(std::tuple_size::value == - internal::count_tuple::value, + using args_pack = mpl::pack; + static_assert(std::tuple_size::value == + internal::count_tuple::value, "set function accepts assign operators only"); - return {std::make_tuple(std::forward(args)...)}; + return {mpl::make_tuple(std::forward(args)...)}; } template internal::columns_t columns(Args... args) { - return {std::make_tuple(std::forward(args)...)}; + return {mpl::make_tuple(std::forward(args)...)}; } /** @@ -404,9 +406,9 @@ namespace sqlite_orm { */ template internal::select_t select(T t, Args... args) { - using args_tuple = std::tuple; + using args_tuple = mpl::pack; internal::validate_conditions(); - return {std::move(t), std::make_tuple(std::forward(args)...)}; + return {std::move(t), mpl::make_tuple(std::forward(args)...)}; } /** diff --git a/dev/serializing_util.h b/dev/serializing_util.h index 125cd666c..1b69d15be 100644 --- a/dev/serializing_util.h +++ b/dev/serializing_util.h @@ -1,6 +1,6 @@ #pragma once -#include // std::index_sequence +#include // std::index_sequence, std::remove_reference #include #include #include @@ -13,6 +13,8 @@ #include "functional/cxx_universal.h" #include "functional/cxx_type_traits_polyfill.h" +#include "functional/tuple.h" +#include "functional/type_at.h" #include "tuple_helper/tuple_iteration.h" #include "error_code.h" #include "serializer_context.h" @@ -124,7 +126,7 @@ namespace sqlite_orm { struct streaming { template auto operator()(const Ts&... ts) const { - return std::forward_as_tuple(*this, ts...); + return mpl::forward_as_tuple(*this, ts...); } template @@ -150,9 +152,9 @@ namespace sqlite_orm { // space + space-separated template std::ostream& operator<<(std::ostream& ss, - std::tuple&, T, Ctx> tpl) { - const auto& conditions = get<1>(tpl); - auto& context = get<2>(tpl); + mpl::tuple&, T, Ctx> tpl) { + const auto& conditions = std::get<1>(tpl); + auto& context = std::get<2>(tpl); iterate_tuple(conditions, [&ss, &context](auto& c) { ss << " " << serialize(c, context); @@ -163,9 +165,9 @@ namespace sqlite_orm { // serialize and stream a tuple of action expressions; // space-separated template - std::ostream& operator<<(std::ostream& ss, std::tuple&, T, Ctx> tpl) { - const auto& actions = get<1>(tpl); - auto& context = get<2>(tpl); + std::ostream& operator<<(std::ostream& ss, mpl::tuple&, T, Ctx> tpl) { + const auto& actions = std::get<1>(tpl); + auto& context = std::get<2>(tpl); iterate_tuple(actions, [&ss, &context, first = true](auto& action) mutable { constexpr std::array sep = {" ", ""}; @@ -178,9 +180,9 @@ namespace sqlite_orm { // comma-separated template std::ostream& operator<<(std::ostream& ss, - std::tuple&, T, Ctx> tpl) { - const auto& args = get<1>(tpl); - auto& context = get<2>(tpl); + mpl::tuple&, T, Ctx> tpl) { + const auto& args = std::get<1>(tpl); + auto& context = std::get<2>(tpl); iterate_tuple(args, [&ss, &context, first = true](auto& arg) mutable { constexpr std::array sep = {", ", ""}; @@ -194,9 +196,9 @@ namespace sqlite_orm { template std::ostream& operator<<( std::ostream& ss, - std::tuple&, const std::tuple...>&, Ctx> tpl) { - const auto& args = get<1>(tpl); - auto& context = get<2>(tpl); + mpl::tuple&, const mpl::tuple...>&, Ctx> tpl) { + const auto& args = std::get<1>(tpl); + auto& context = std::get<2>(tpl); iterate_tuple(args, [&ss, &context, first = true](auto& arg) mutable { constexpr std::array sep = {", ", ""}; @@ -209,9 +211,9 @@ namespace sqlite_orm { // comma-separated template std::ostream& operator<<(std::ostream& ss, - std::tuple&, C, Ctx> tpl) { - const auto& args = get<1>(tpl); - auto& context = get<2>(tpl); + mpl::tuple&, C, Ctx> tpl) { + const auto& args = std::get<1>(tpl); + auto& context = std::get<2>(tpl); constexpr std::array sep = {", ", ""}; for(size_t i = 0, first = true; i < args.size(); ++i) { @@ -223,8 +225,8 @@ namespace sqlite_orm { // stream a vector of already serialized strings; // comma-separated template - std::ostream& operator<<(std::ostream& ss, std::tuple&, C> tpl) { - const auto& strings = get<1>(tpl); + std::ostream& operator<<(std::ostream& ss, mpl::tuple&, C> tpl) { + const auto& strings = std::get<1>(tpl); constexpr std::array sep = {", ", ""}; for(size_t i = 0, first = true; i < strings.size(); ++i) { @@ -239,7 +241,7 @@ namespace sqlite_orm { // 3. qualifier, identifier, alias template std::ostream& operator<<(std::ostream& ss, - std::tuple&, Strings...> tpl) { + mpl::tuple&, Strings...> tpl) { stream_identifier(ss, tpl, streaming_identifier.offset_index(std::index_sequence_for{})); return ss; } @@ -252,8 +254,8 @@ namespace sqlite_orm { // // comma-separated template - std::ostream& operator<<(std::ostream& ss, std::tuple&, C> tpl) { - const auto& identifiers = get<1>(tpl); + std::ostream& operator<<(std::ostream& ss, mpl::tuple&, C> tpl) { + const auto& identifiers = std::get<1>(tpl); constexpr std::array sep = {", ", ""}; bool first = true; @@ -267,9 +269,9 @@ namespace sqlite_orm { // stream placeholders as part of a values clause template std::ostream& operator<<(std::ostream& ss, - std::tuple&, Ts...> tpl) { - const size_t& columnsCount = get<1>(tpl); - const ptrdiff_t& valuesCount = get<2>(tpl); + mpl::tuple&, Ts...> tpl) { + const size_t& columnsCount = std::get<1>(tpl); + const ptrdiff_t& valuesCount = std::get<2>(tpl); if(!valuesCount || !columnsCount) { return ss; @@ -296,9 +298,9 @@ namespace sqlite_orm { // comma-separated template std::ostream& operator<<(std::ostream& ss, - std::tuple&, Table, const bool&> tpl) { - const auto& table = get<1>(tpl); - const bool& qualified = get<2>(tpl); + mpl::tuple&, Table, const bool&> tpl) { + const auto& table = std::get<1>(tpl); + const bool& qualified = std::get<2>(tpl); table.for_each_column([&ss, &tableName = qualified ? table.name : std::string{}, first = true]( const column_identifier& column) mutable { @@ -313,8 +315,8 @@ namespace sqlite_orm { // comma-separated template std::ostream& operator<<(std::ostream& ss, - std::tuple&, Table> tpl) { - const auto& table = get<1>(tpl); + mpl::tuple&, Table> tpl) { + const auto& table = std::get<1>(tpl); table.template for_each_column_excluding( [&ss, first = true](const column_identifier& column) mutable { @@ -330,11 +332,11 @@ namespace sqlite_orm { template std::ostream& operator<<(std::ostream& ss, - std::tuple&, PredFnCls, L, Ctx, Obj> tpl) { - using check_if_excluded = polyfill::remove_cvref_t>; - auto& excluded = get<2>(tpl); - auto& context = get<3>(tpl); - auto& object = get<4>(tpl); + mpl::tuple&, PredFnCls, L, Ctx, Obj> tpl) { + using check_if_excluded = polyfill::remove_cvref_t>; + auto& excluded = std::get<2>(tpl); + auto& context = std::get<3>(tpl); + auto& object = std::get<4>(tpl); using object_type = polyfill::remove_cvref_t; auto& table = pick_table(context.db_objects); @@ -355,9 +357,9 @@ namespace sqlite_orm { // comma-separated template std::ostream& operator<<(std::ostream& ss, - std::tuple&, T, Ctx> tpl) { - const auto& columns = get<1>(tpl); - auto& context = get<2>(tpl); + mpl::tuple&, T, Ctx> tpl) { + const auto& columns = std::get<1>(tpl); + auto& context = std::get<2>(tpl); iterate_tuple(columns, [&ss, &context, first = true](auto& colRef) mutable { const std::string* columnName = find_column_name(context.db_objects, colRef); @@ -374,13 +376,13 @@ namespace sqlite_orm { template std::ostream& operator<<(std::ostream& ss, - std::tuple&, + mpl::tuple&, const column_constraints&, const bool&, Ctx> tpl) { - const auto& column = get<1>(tpl); - const bool& isNotNull = get<2>(tpl); - auto& context = get<3>(tpl); + const auto& column = std::get<1>(tpl); + const bool& isNotNull = std::get<2>(tpl); + auto& context = std::get<3>(tpl); using constraints_type = constraints_type_t>; constexpr size_t constraintsCount = std::tuple_size::value; @@ -393,7 +395,7 @@ namespace sqlite_orm { iterate_tuple(column.constraints, [&constraintsStrings, &primaryKeyIndex, &autoincrementIndex, &tupleIndex, &context]( auto& constraint) { - using constraint_type = std::decay_t; + using constraint_type = polyfill::remove_cvref_t; constraintsStrings.push_back(serialize(constraint, context)); if(is_primary_key_v) { primaryKeyIndex = tupleIndex; diff --git a/dev/statement_serializer.h b/dev/statement_serializer.h index 07525ae4d..9b0b29760 100644 --- a/dev/statement_serializer.h +++ b/dev/statement_serializer.h @@ -15,6 +15,8 @@ #include "functional/cxx_universal.h" #include "functional/cxx_functional_polyfill.h" #include "functional/mpl.h" +#include "functional/pack.h" +#include "functional/type_at.h" #include "tuple_helper/tuple_filter.h" #include "ast/upsert_clause.h" #include "ast/excluded.h" @@ -211,16 +213,16 @@ namespace sqlite_orm { } }; - template - struct statement_serializer, std::tuple>, void> { - using statement_type = upsert_clause, std::tuple>; + template + struct statement_serializer> { + using statement_type = T; template std::string operator()(const statement_type& statement, const Ctx& context) const { std::stringstream ss; ss << "ON CONFLICT"; iterate_tuple(statement.target_args, [&ss, &context](auto& value) { - using value_type = std::decay_t; + using value_type = std::remove_reference_t; auto needParenthesis = std::is_member_pointer::value; ss << ' '; if(needParenthesis) { @@ -699,9 +701,7 @@ namespace sqlite_orm { ss << "NOT IN"; } ss << " "; - using args_type = std::tuple; - constexpr bool theOnlySelect = - std::tuple_size::value == 1 && is_select_v>; + constexpr bool theOnlySelect = sizeof...(Args) == 1 && is_select_v>; if(!theOnlySelect) { ss << "("; } @@ -837,17 +837,17 @@ namespace sqlite_orm { } }; - template - struct statement_serializer, std::tuple>, void> { - using statement_type = foreign_key_t, std::tuple>; + template + struct statement_serializer> { + using statement_type = FK; template std::string operator()(const statement_type& fk, const Ctx& context) const { std::stringstream ss; ss << "FOREIGN KEY(" << streaming_mapped_columns_expressions(fk.columns, context) << ") REFERENCES "; { - using references_type_t = typename std::decay_t::references_type; - using first_reference_t = std::tuple_element_t<0, references_type_t>; + using references_type_t = typename std::remove_reference_t::references_type; + using first_reference_t = mpl::element_at_t<0, references_type_t>; using first_reference_mapped_type = table_type_of_t; auto refTableName = lookup_table_name(context.db_objects); ss << streaming_identifier(refTableName); @@ -942,8 +942,7 @@ namespace sqlite_orm { template std::string operator()(const statement_type& statement, const Ctx& context) const { - using expression_type = std::decay_t; - using object_type = typename expression_object_type::type; + using object_type = typename expression_object_type::type; auto& table = pick_table(context.db_objects); std::stringstream ss; ss << "REPLACE INTO " << streaming_identifier(table.name) << " (" @@ -964,10 +963,9 @@ namespace sqlite_orm { template std::string operator()(const statement_type& ins, const Ctx& context) const { - constexpr size_t colsCount = std::tuple_size>::value; + constexpr size_t colsCount = sizeof...(Cols); static_assert(colsCount > 0, "Use insert or replace with 1 argument instead"); - using expression_type = std::decay_t; - using object_type = typename expression_object_type::type; + using object_type = typename expression_object_type::type; auto& table = pick_table(context.db_objects); std::stringstream ss; ss << "INSERT INTO " << streaming_identifier(table.name) << " "; @@ -975,7 +973,7 @@ namespace sqlite_orm { << "VALUES ("; iterate_tuple(ins.columns.columns, [&ss, &context, &object = get_ref(ins.obj), first = true](auto& memberPointer) mutable { - using member_pointer_type = std::decay_t; + using member_pointer_type = polyfill::remove_cvref_t; static_assert(!is_setter_v, "Unable to use setter within insert explicit"); @@ -994,8 +992,7 @@ namespace sqlite_orm { template std::string operator()(const statement_type& statement, const Ctx& context) const { - using expression_type = std::decay_t; - using object_type = typename expression_object_type::type; + using object_type = typename expression_object_type::type; auto& table = pick_table(context.db_objects); std::stringstream ss; @@ -1087,7 +1084,7 @@ namespace sqlite_orm { std::string operator()(const statement_type& statement, const Ctx& context) const { using object_type = typename expression_object_type::type; auto& table = pick_table(context.db_objects); - using is_without_rowid = typename std::decay_t::is_without_rowid; + using is_without_rowid = typename std::remove_reference_t::is_without_rowid; std::vector> columnNames; table.template for_each_column_excluding< @@ -1172,7 +1169,7 @@ namespace sqlite_orm { ss << "REPLACE"; } iterate_tuple(statement.args, [&context, &ss](auto& value) { - using value_type = std::decay_t; + using value_type = polyfill::remove_cvref_t; ss << ' '; if(is_columns_v) { auto newContext = context; @@ -1226,8 +1223,7 @@ namespace sqlite_orm { template std::string operator()(const statement_type& rep, const Ctx& context) const { - using expression_type = std::decay_t; - using object_type = typename expression_object_type::type; + using object_type = typename expression_object_type::type; auto& table = pick_table(context.db_objects); std::stringstream ss; @@ -1248,7 +1244,7 @@ namespace sqlite_orm { std::string operator()(const statement_type& statement, const Ctx& context) const { using object_type = typename expression_object_type::type; auto& table = pick_table(context.db_objects); - using is_without_rowid = typename std::decay_t::is_without_rowid; + using is_without_rowid = typename std::remove_reference_t::is_without_rowid; std::vector> columnNames; table.template for_each_column_excluding< @@ -1437,12 +1433,12 @@ namespace sqlite_orm { table_name_collector collector([&context](const std::type_index& ti) { return find_table_name(context.db_objects, ti); }); - constexpr bool explicitFromItemsCount = count_tuple, is_from>::value; + constexpr bool explicitFromItemsCount = count_tuple, is_from>::value; if(!explicitFromItemsCount) { iterate_ast(sel.col, collector); iterate_ast(sel.conditions, collector); join_iterator()([&collector, &context](const auto& c) { - using original_join_type = typename std::decay_t::join_type::type; + using original_join_type = typename std::remove_reference_t::join_type::type; using cross_join_type = mapped_type_proxy_t; auto crossJoinedTableName = lookup_table_name(context.db_objects); auto tableAliasString = alias_extractor::get(); @@ -1502,15 +1498,15 @@ namespace sqlite_orm { if(statement.unique) { ss << "UNIQUE "; } - using elements_type = typename std::decay_t::elements_type; - using head_t = typename std::tuple_element_t<0, elements_type>::column_type; + using elements_type = typename std::remove_reference_t::elements_type; + using head_t = typename mpl::element_at_t<0, elements_type>::column_type; using indexed_type = table_type_of_t; ss << "INDEX IF NOT EXISTS " << streaming_identifier(statement.name) << " ON " << streaming_identifier(lookup_table_name(context.db_objects)); std::vector columnNames; std::string whereString; iterate_tuple(statement.elements, [&columnNames, &context, &whereString](auto& value) { - using value_type = std::decay_t; + using value_type = polyfill::remove_cvref_t; if(!is_where_v) { auto newContext = context; newContext.use_parentheses = false; @@ -1529,17 +1525,15 @@ namespace sqlite_orm { } }; - template - struct statement_serializer, void> { - using statement_type = from_t; + template + struct statement_serializer> { + using statement_type = T; template std::string operator()(const statement_type&, const Ctx& context) const { - using tuple = std::tuple; - std::stringstream ss; ss << "FROM "; - iterate_tuple([&context, &ss, first = true](auto* item) mutable { + iterate_pack(typename statement_type::pack_type{}, [&context, &ss, first = true](auto* item) mutable { using from_type = std::remove_pointer_t; constexpr std::array sep = {", ", ""}; @@ -1700,7 +1694,7 @@ namespace sqlite_orm { << serialize(statement.base, context); ss << " BEGIN "; iterate_tuple(statement.elements, [&ss, &context](auto& element) { - using element_type = std::decay_t; + using element_type = polyfill::remove_cvref_t; if(is_select_v) { auto newContext = context; newContext.use_parentheses = false; diff --git a/dev/storage.h b/dev/storage.h index 29e310ea9..032b8473c 100644 --- a/dev/storage.h +++ b/dev/storage.h @@ -9,7 +9,6 @@ #include // std::stringstream #include // std::map #include // std::vector -#include // std::tuple_size, std::tuple, std::make_tuple, std::tie #include // std::forward, std::pair #include // std::for_each, std::ranges::for_each #include "functional/cxx_optional.h" @@ -102,7 +101,7 @@ namespace sqlite_orm { template void create_table(sqlite3* db, const std::string& tableName, const Table& table) { - using table_type = std::decay_t; + using table_type = std::remove_reference_t; using context_t = serializer_context; std::stringstream ss; @@ -173,8 +172,8 @@ namespace sqlite_orm { template void assert_mapped_type() const { - using mapped_types_tuple = std::tuple; - static_assert(mpl::invoke_t, mapped_types_tuple>::value, + using mapped_types_pack = mpl::pack; + static_assert(mpl::invoke_t, mapped_types_pack>::value, "type is not mapped to a storage"); } @@ -458,11 +457,7 @@ namespace sqlite_orm { * @param m is a class member pointer (the same you passed into make_column). * @return group_concat query result. */ - template, - std::enable_if_t::value >= 1, bool> = true> + template= 1, bool> = true> std::string group_concat(F O::*m, Args&&... args) { return this->group_concat_internal(m, {}, std::forward(args)...); } @@ -567,8 +562,7 @@ namespace sqlite_orm { */ template> std::vector select(T m, Args... args) { - static_assert(!is_base_of_template_v || - std::tuple_size>::value == 0, + static_assert(!is_base_of_template_v || sizeof...(Args) == 0, "Cannot use args with a compound operator"); auto statement = this->prepare(sqlite_orm::select(std::move(m), std::forward(args)...)); return this->execute(statement); @@ -611,7 +605,7 @@ namespace sqlite_orm { std::stringstream ss; ss << "{ "; table.for_each_column([&ss, &object, first = true](auto& column) mutable { - using column_type = std::decay_t; + using column_type = std::remove_reference_t; using field_type = typename column_type::field_type; constexpr std::array sep = {", ", ""}; @@ -1134,7 +1128,7 @@ namespace sqlite_orm { template int64 execute(const prepared_statement_t>& statement) { - using statement_type = std::decay_t; + using statement_type = std::remove_reference_t; using expression_type = typename statement_type::expression_type; using object_type = typename expression_object_type::type; @@ -1152,7 +1146,7 @@ namespace sqlite_orm { template, is_replace_range>, bool> = true> void execute(const prepared_statement_t& statement) { - using statement_type = std::decay_t; + using statement_type = std::remove_reference_t; using expression_type = typename statement_type::expression_type; using object_type = typename expression_object_type::type; @@ -1193,7 +1187,7 @@ namespace sqlite_orm { template, is_insert_range>, bool> = true> int64 execute(const prepared_statement_t& statement) { - using statement_type = std::decay_t; + using statement_type = std::remove_reference_t; using expression_type = typename statement_type::expression_type; using object_type = typename expression_object_type::type; @@ -1201,7 +1195,7 @@ namespace sqlite_orm { auto processObject = [&table = this->get_table(), bind_value = field_value_binder{stmt}](auto& object) mutable { - using is_without_rowid = typename std::decay_t::is_without_rowid; + using is_without_rowid = typename std::remove_reference_t::is_without_rowid; table.template for_each_column_excluding< mpl::conjunction>, mpl::disjunction_fn>>( @@ -1247,7 +1241,7 @@ namespace sqlite_orm { template void execute(const prepared_statement_t>& statement) { - using statement_type = std::decay_t; + using statement_type = std::remove_reference_t; using expression_type = typename statement_type::expression_type; using object_type = typename expression_object_type::type; diff --git a/dev/storage_base.h b/dev/storage_base.h index 9131e49c1..db0172b32 100644 --- a/dev/storage_base.h +++ b/dev/storage_base.h @@ -239,7 +239,7 @@ namespace sqlite_orm { auto name = ss.str(); using args_tuple = typename callable_arguments::args_tuple; using return_type = typename callable_arguments::return_type; - constexpr auto argsCount = std::is_same>::value + constexpr auto argsCount = std::is_same>::value ? -1 : int(std::tuple_size::value); this->scalarFunctions.emplace_back(new user_defined_scalar_function_t{ @@ -301,7 +301,7 @@ namespace sqlite_orm { auto name = ss.str(); using args_tuple = typename callable_arguments::args_tuple; using return_type = typename callable_arguments::return_type; - constexpr auto argsCount = std::is_same>::value + constexpr auto argsCount = std::is_same>::value ? -1 : int(std::tuple_size::value); this->aggregateFunctions.emplace_back(new user_defined_aggregate_function_t{ @@ -317,7 +317,7 @@ namespace sqlite_orm { args_tuple argsTuple; using tuple_size = std::tuple_size; values_to_tuple{}(values, argsTuple, argsCount); - call(function, &F::step, move(argsTuple)); + call(function, &F::step, std::move(argsTuple)); }, /* finalCall = */ [](sqlite3_context* context, void* functionVoidPointer) { diff --git a/dev/storage_impl.h b/dev/storage_impl.h index 701ffa43c..37dc2998a 100644 --- a/dev/storage_impl.h +++ b/dev/storage_impl.h @@ -41,7 +41,7 @@ namespace sqlite_orm { std::string find_table_name(const DBOs& dbObjects, const std::type_index& ti) { std::string res; iterate_tuple(dbObjects, tables_index_sequence{}, [&ti, &res](const auto& table) { - using table_type = std::decay_t; + using table_type = std::remove_reference_t; if(ti == typeid(object_type_t)) { res = table.name; } diff --git a/dev/storage_lookup.h b/dev/storage_lookup.h index d7ce8e3fd..2fe35dbb0 100644 --- a/dev/storage_lookup.h +++ b/dev/storage_lookup.h @@ -1,10 +1,10 @@ #pragma once #include // std::true_type, std::false_type, std::remove_const, std::enable_if -#include #include "functional/cxx_universal.h" #include "functional/cxx_type_traits_polyfill.h" +#include "functional/unique_tuple.h" #include "type_traits.h" namespace sqlite_orm { @@ -14,7 +14,7 @@ namespace sqlite_orm { struct storage_t; template - using db_objects_tuple = std::tuple; + using db_objects_tuple = mpl::uple; template struct is_storage : std::false_type {}; @@ -65,7 +65,7 @@ namespace sqlite_orm { struct storage_pick_table> : storage_pick_table {}; #else template - struct storage_pick_table> : storage_pick_table {}; + struct storage_pick_table> : storage_pick_table {}; #endif /** @@ -92,7 +92,7 @@ namespace sqlite_orm { struct storage_find_table> : storage_find_table {}; #else template - struct storage_find_table> : storage_find_table {}; + struct storage_find_table> : storage_find_table {}; #endif /** diff --git a/dev/table.h b/dev/table.h index 8ecc5a976..1d8ba1acc 100644 --- a/dev/table.h +++ b/dev/table.h @@ -3,7 +3,6 @@ #include // std::string #include // std::remove_reference, std::is_same, std::decay #include // std::vector -#include // std::tuple_size, std::tuple_element #include // std::forward, std::move #include "functional/cxx_universal.h" @@ -11,8 +10,10 @@ #include "functional/cxx_functional_polyfill.h" #include "functional/static_magic.h" #include "functional/mpl.h" +#include "functional/type_at.h" +#include "functional/index_sequence_util.h" +#include "functional/tuple.h" #include "typed_comparator.h" -#include "tuple_helper/index_sequence_util.h" #include "tuple_helper/tuple_filter.h" #include "tuple_helper/tuple_traits.h" #include "tuple_helper/tuple_iteration.h" @@ -40,7 +41,7 @@ namespace sqlite_orm { template struct table_t : basic_table { using object_type = T; - using elements_type = std::tuple; + using elements_type = mpl::tuple; static constexpr bool is_without_rowid_v = WithoutRowId; using is_without_rowid = polyfill::bool_constant; @@ -48,7 +49,8 @@ namespace sqlite_orm { elements_type elements; #ifndef SQLITE_ORM_AGGREGATE_BASES_SUPPORTED - table_t(std::string name_, elements_type elements_) : basic_table{move(name_)}, elements{move(elements_)} {} + table_t(std::string name_, elements_type elements_) : + basic_table{move(name_)}, elements{std::move(elements_)} {} #endif table_t without_rowid() const { @@ -106,8 +108,9 @@ namespace sqlite_orm { using generated_op_index_sequence = filter_tuple_sequence_t, is_generated_always>; - constexpr size_t opIndex = first_index_sequence_value(generated_op_index_sequence{}); - result = &get(column.constraints).storage; + constexpr size_t opIndex = + mpl::first_index_sequence_value(generated_op_index_sequence{}); + result = &std::get(column.constraints).storage; }); #endif return result; @@ -288,10 +291,10 @@ namespace sqlite_orm { * * The mapped object type is determined implicitly from the first column definition. */ - template>::object_type> + template::object_type> internal::table_t make_table(std::string name, Cs... args) { SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES( - return {move(name), std::make_tuple(std::forward(args)...)}); + return {move(name), mpl::make_tuple(std::forward(args)...)}); } /** @@ -302,6 +305,6 @@ namespace sqlite_orm { template internal::table_t make_table(std::string name, Cs... args) { SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES( - return {move(name), std::make_tuple(std::forward(args)...)}); + return {move(name), mpl::make_tuple(std::forward(args)...)}); } } diff --git a/dev/triggers.h b/dev/triggers.h index 20b18fef1..671539a8e 100644 --- a/dev/triggers.h +++ b/dev/triggers.h @@ -1,11 +1,10 @@ #pragma once -#include -#include #include -#include +#include // std::move, std::forward #include "functional/cxx_universal.h" +#include "functional/tuple.h" #include "optional_container.h" // NOTE Idea : Maybe also implement a custom trigger system to call a c++ callback when a trigger triggers ? @@ -26,7 +25,7 @@ namespace sqlite_orm { */ template struct partial_trigger_t { - using statements_type = std::tuple; + using statements_type = mpl::tuple; /** * Base of the trigger (contains its type, timing and associated table) @@ -38,7 +37,7 @@ namespace sqlite_orm { statements_type statements; partial_trigger_t(T trigger_base, S... statements) : - base{std::move(trigger_base)}, statements{std::make_tuple(std::forward(statements)...)} {} + base{std::move(trigger_base)}, statements{mpl::make_tuple(std::forward(statements)...)} {} partial_trigger_t &end() { return *this; @@ -156,7 +155,7 @@ namespace sqlite_orm { */ template struct trigger_update_type_t : trigger_type_base_t { - using columns_type = std::tuple; + using columns_type = mpl::tuple; /** * Contains the columns the trigger is watching. Will only @@ -165,7 +164,7 @@ namespace sqlite_orm { columns_type columns; trigger_update_type_t(trigger_timing timing, trigger_type type, Cs... columns) : - trigger_type_base_t(timing, type), columns(std::make_tuple(std::forward(columns)...)) {} + trigger_type_base_t(timing, type), columns(mpl::make_tuple(std::forward(columns)...)) {} template trigger_base_t> on() { diff --git a/dev/tuple_helper/index_sequence_util.h b/dev/tuple_helper/index_sequence_util.h deleted file mode 100644 index 556c21142..000000000 --- a/dev/tuple_helper/index_sequence_util.h +++ /dev/null @@ -1,51 +0,0 @@ -#pragma once - -#include // std::index_sequence, std::make_index_sequence - -#include "../functional/cxx_universal.h" -#ifdef SQLITE_ORM_RELAXED_CONSTEXPR_SUPPORTED -#include -#endif - -namespace sqlite_orm { - namespace internal { - /** - * Get the first value of an index_sequence. - */ - template - SQLITE_ORM_CONSTEVAL size_t first_index_sequence_value(std::index_sequence) { - return I; - } - -#ifdef SQLITE_ORM_RELAXED_CONSTEXPR_SUPPORTED - /** - * Reorder the values of an index_sequence according to the positions from a second sequence. - */ - template - SQLITE_ORM_CONSTEVAL auto reorder_index_sequence(std::index_sequence, - std::index_sequence) { - constexpr std::array values{Value...}; - return std::index_sequence{}; - } - - template - SQLITE_ORM_CONSTEVAL std::index_sequence reorder_index_sequence(std::index_sequence, - std::index_sequence) { - return {}; - } - - inline SQLITE_ORM_CONSTEVAL std::index_sequence<> reorder_index_sequence(std::index_sequence<>, - std::index_sequence<>) { - return {}; - } - - /** - * Reverse the values of an index_sequence. - */ - template - SQLITE_ORM_CONSTEVAL auto reverse_index_sequence(std::index_sequence) { - return reorder_index_sequence(std::index_sequence{}, std::make_index_sequence{}); - } -#endif - } -} diff --git a/dev/tuple_helper/tuple_filter.h b/dev/tuple_helper/tuple_filter.h index 39c1f8d92..0ec7b2f44 100644 --- a/dev/tuple_helper/tuple_filter.h +++ b/dev/tuple_helper/tuple_filter.h @@ -1,55 +1,41 @@ #pragma once -#include // std::integral_constant, std::index_sequence, std::conditional, std::declval -#include // std::tuple +#include // std::integral_constant, std::index_sequence, std::make_index_sequence, std::conditional, std::declval #include "../functional/cxx_universal.h" +#include "../functional/index_sequence_util.h" +#include "../functional/pack_util.h" +#include "../functional/tuple.h" namespace sqlite_orm { namespace internal { - template - using tuple_cat_t = decltype(std::tuple_cat(std::declval()...)); + template + using tuple_cat_t = mpl::flatten_types_t; template - struct conc_tuple { - using type = tuple_cat_t; - }; + struct conc_tuple : mpl::flatten_types {}; template struct tuple_from_index_sequence; - template - struct tuple_from_index_sequence> { - using type = std::tuple...>; + template class Tuple, class... T, size_t... Idx> + struct tuple_from_index_sequence, std::index_sequence> { + using type = Tuple>...>; }; template using tuple_from_index_sequence_t = typename tuple_from_index_sequence::type; - template - struct concat_idx_seq { - using type = std::index_sequence<>; - }; - - template - struct concat_idx_seq> { - using type = std::index_sequence; - }; - - template - struct concat_idx_seq, std::index_sequence, Seq...> - : concat_idx_seq, Seq...> {}; - template class Pred, template class Proj, class Seq> struct filter_tuple_sequence; #ifndef SQLITE_ORM_BROKEN_VARIADIC_PACK_EXPANSION template class Pred, template class Proj, size_t... Idx> struct filter_tuple_sequence> - : concat_idx_seq>>::value, - std::index_sequence, - std::index_sequence<>>...> {}; + : mpl::flatten_idxseq>>::value, + std::index_sequence, + std::index_sequence<>>...> {}; #else template class Pred, class SFINAE = void> struct tuple_seq_single { @@ -63,7 +49,7 @@ namespace sqlite_orm { template class Pred, template class Proj, size_t... Idx> struct filter_tuple_sequence> - : concat_idx_seq>, Pred>::type...> {}; + : mpl::flatten_idxseq>, Pred>::type...> {}; #endif template // std::tuple, std::get, std::tuple_element, std::tuple_size #include // std::index_sequence, std::make_index_sequence #include // std::forward, std::move #include "../functional/cxx_universal.h" #include "../functional/cxx_type_traits_polyfill.h" #include "../functional/cxx_functional_polyfill.h" -#include "index_sequence_util.h" +#include "../functional/index_sequence_util.h" namespace sqlite_orm { namespace internal { + namespace mpl { + template + struct pack; + + template + struct uple; + } // got it form here https://stackoverflow.com/questions/7858817/unpacking-a-tuple-to-call-a-matching-function-pointer template auto call_impl(Function& f, FunctionPointer functionPointer, Tuple t, std::index_sequence) { - return (f.*functionPointer)(std::get(move(t))...); + return (f.*functionPointer)(std::get(std::move(t))...); } template auto call(Function& f, FunctionPointer functionPointer, Tuple t) { constexpr size_t size = std::tuple_size::value; - return call_impl(f, functionPointer, move(t), std::make_index_sequence{}); + return call_impl(f, functionPointer, std::move(t), std::make_index_sequence{}); } template auto call(Function& f, Tuple t) { - return call(f, &Function::operator(), move(t)); + return call(f, &Function::operator(), std::move(t)); } #if defined(SQLITE_ORM_FOLD_EXPRESSIONS_SUPPORTED) && defined(SQLITE_ORM_IF_CONSTEXPR_SUPPORTED) - template - void iterate_tuple(const Tpl& tpl, std::index_sequence, L&& lambda) { + template + void iterate_tuple(const Tpl& tpl, std::index_sequence, L&& lambda) { if constexpr(reversed) { - iterate_tuple(tpl, reverse_index_sequence(std::index_sequence{}), std::forward(lambda)); + iterate_tuple(tpl, mpl::reverse_index_sequence(std::index_sequence{}), std::forward(lambda)); } else { - (lambda(std::get(tpl)), ...); + (lambda(std::get(tpl)), ...); } } #else template void iterate_tuple(const Tpl& /*tpl*/, std::index_sequence<>, L&& /*lambda*/) {} - template - void iterate_tuple(const Tpl& tpl, std::index_sequence, L&& lambda) { + template + void iterate_tuple(const Tpl& tpl, std::index_sequence, L&& lambda) { #ifdef SQLITE_ORM_IF_CONSTEXPR_SUPPORTED if constexpr(reversed) { #else if(reversed) { #endif - iterate_tuple(tpl, std::index_sequence{}, std::forward(lambda)); + iterate_tuple(tpl, std::index_sequence{}, std::forward(lambda)); lambda(std::get(tpl)); } else { - lambda(std::get(tpl)); - iterate_tuple(tpl, std::index_sequence{}, std::forward(lambda)); + int poormansfold[] = {(lambda(std::get(tpl)), int{}), (lambda(std::get(tpl)), int{})...}; + (void)poormansfold; } } #endif @@ -65,28 +71,34 @@ namespace sqlite_orm { } #ifdef SQLITE_ORM_FOLD_EXPRESSIONS_SUPPORTED - template - void iterate_tuple(std::index_sequence, L&& lambda) { - (lambda((std::tuple_element_t*)nullptr), ...); + template + void iterate_tuple(const mpl::uple& tpl, L&& lambda) { + (lambda(std::get(tpl)), ...); } #else - template - void iterate_tuple(std::index_sequence<>, L&& /*lambda*/) {} - - template - void iterate_tuple(std::index_sequence, L&& lambda) { - lambda((std::tuple_element_t*)nullptr); - iterate_tuple(std::index_sequence{}, std::forward(lambda)); + template + void iterate_tuple(const mpl::uple& tpl, L&& lambda) { + int poormansfold[] = {int{}, (lambda(std::get(tpl)), int{})...}; + (void)poormansfold; } #endif - template - void iterate_tuple(L&& lambda) { - iterate_tuple(std::make_index_sequence::value>{}, std::forward(lambda)); + +#ifdef SQLITE_ORM_FOLD_EXPRESSIONS_SUPPORTED + template + void iterate_pack(mpl::pack, L&& lambda) { + (lambda((X*)nullptr), ...); + } +#else + template + void iterate_pack(mpl::pack, L&& lambda) { + int poormansfold[] = {int{}, (lambda((X*)nullptr), int{})...}; + (void)poormansfold; } +#endif - template - R create_from_tuple(Tpl&& tpl, std::index_sequence, Projection project = {}) { - return R{polyfill::invoke(project, std::get(std::forward(tpl)))...}; + template + R create_from_tuple(Tpl&& tpl, std::index_sequence, Projection project = {}) { + return R{polyfill::invoke(project, std::get(std::forward(tpl)))...}; } template diff --git a/dev/tuple_helper/tuple_traits.h b/dev/tuple_helper/tuple_traits.h index 7de97f8f7..56f3ac064 100644 --- a/dev/tuple_helper/tuple_traits.h +++ b/dev/tuple_helper/tuple_traits.h @@ -1,8 +1,5 @@ #pragma once -#include // std::is_same -#include - #include "../functional/cxx_type_traits_polyfill.h" #include "../functional/mpl.h" @@ -13,8 +10,9 @@ namespace sqlite_orm { */ template class TraitFn, class Tuple> struct tuple_has {}; - template class TraitFn, class... Types> - struct tuple_has> : polyfill::disjunction...> {}; + + template class TraitFn, template class Tuple, class... Types> + struct tuple_has> : polyfill::disjunction...> {}; /* * Trait metafunction class that checks whether a tuple contains a type with given trait. diff --git a/dev/tuple_helper/tuple_transformer.h b/dev/tuple_helper/tuple_transformer.h index 9c7a73c43..46ecf01df 100644 --- a/dev/tuple_helper/tuple_transformer.h +++ b/dev/tuple_helper/tuple_transformer.h @@ -2,18 +2,13 @@ #include // std::tuple -#include "../functional/mpl.h" +#include "../functional/pack_util.h" namespace sqlite_orm { namespace internal { template class Op> - struct tuple_transformer; - - template class Op> - struct tuple_transformer, Op> { - using type = std::tuple...>; - }; + struct tuple_transformer : mpl::transform_types {}; /* * Transform specified tuple. @@ -21,6 +16,6 @@ namespace sqlite_orm { * `Op` is a metafunction operation. */ template class Op> - using transform_tuple_t = typename tuple_transformer::type; + using transform_tuple_t = mpl::transform_types_t; } } diff --git a/dev/values.h b/dev/values.h index a42b52e68..ced45afa7 100644 --- a/dev/values.h +++ b/dev/values.h @@ -1,11 +1,11 @@ #pragma once #include // std::vector -#include // std::tuple #include // std::forward #include "functional/cxx_universal.h" #include "functional/cxx_type_traits_polyfill.h" +#include "functional/tuple.h" namespace sqlite_orm { @@ -13,7 +13,7 @@ namespace sqlite_orm { template struct values_t { - using args_tuple = std::tuple; + using args_tuple = mpl::tuple; args_tuple tuple; }; diff --git a/dev/values_to_tuple.h b/dev/values_to_tuple.h index a85201d9a..4dfbb89b8 100644 --- a/dev/values_to_tuple.h +++ b/dev/values_to_tuple.h @@ -2,9 +2,9 @@ #include #include // std::index_sequence, std::make_index_sequence -#include // std::tuple, std::tuple_size, std::get #include "functional/cxx_universal.h" +#include "functional/tuple.h" #include "row_extractor.h" #include "arg_values.h" @@ -18,7 +18,7 @@ namespace sqlite_orm { (*this)(values, tuple, std::make_index_sequence::value>{}); } - void operator()(sqlite3_value** values, std::tuple& tuple, int argsCount) const { + void operator()(sqlite3_value** values, mpl::tuple& tuple, int argsCount) const { std::get<0>(tuple) = arg_values(argsCount, values); } diff --git a/dev/view.h b/dev/view.h index f96d6ff23..78eaa41c2 100644 --- a/dev/view.h +++ b/dev/view.h @@ -3,7 +3,6 @@ #include #include // std::string #include // std::forward, std::move -#include // std::tuple, std::make_tuple #include "row_extractor.h" #include "error_code.h" @@ -37,7 +36,7 @@ namespace sqlite_orm { get_all_t, Args...> args; view_t(storage_type& stor, decltype(connection) conn, Args&&... args_) : - storage(stor), connection(std::move(conn)), args{std::make_tuple(std::forward(args_)...)} {} + storage(stor), connection(std::move(conn)), args{mpl::make_tuple(std::forward(args_)...)} {} size_t size() { return this->storage.template count(); diff --git a/include/sqlite_orm/sqlite_orm.h b/include/sqlite_orm/sqlite_orm.h index 1eae31c21..afe56fbea 100644 --- a/include/sqlite_orm/sqlite_orm.h +++ b/include/sqlite_orm/sqlite_orm.h @@ -46,12 +46,22 @@ using std::nullptr_t; #define SQLITE_ORM_HAS_INCLUDE(file) 0L #endif +// If possible, use an intrinsic provided by Clang +#if defined(__has_builtin) +#if __has_builtin(__type_pack_element) +#define SQLITE_ORM_HAS_TYPE_PACK_ELEMENT_INTRINSIC +#endif +#endif + #if __cpp_aggregate_nsdmi >= 201304L #define SQLITE_ORM_AGGREGATE_NSDMI_SUPPORTED #endif #if __cpp_constexpr >= 201304L #define SQLITE_ORM_RELAXED_CONSTEXPR_SUPPORTED +#define SQLITE_ORM_NONCONST_CONSTEXPR constexpr +#else +#define SQLITE_ORM_NONCONST_CONSTEXPR #endif #if __cpp_noexcept_function_type >= 201510L @@ -91,6 +101,10 @@ using std::nullptr_t; #define SQLITE_ORM_NOUNIQUEADDRESS #endif +#if __cpp_conditional_explicit >= 201806L +#define SQLITE_ORM_CONDITIONAL_EXPLICIT_SUPPORTED +#endif + #if __cpp_consteval >= 201811L #define SQLITE_ORM_CONSTEVAL consteval #else @@ -132,8 +146,35 @@ using std::nullptr_t; // Because we know what we are doing, we suppress the diagnostic message #define SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES(...) SQLITE_ORM_CLANG_SUPPRESS("-Wmissing-braces", __VA_ARGS__) -#if defined(_MSC_VER) && (_MSC_VER < 1920) +#if defined(_MSC_VER) && !defined(__clang__) // MSVC +#define SQLITE_ORM_MSVC_EMPTYBASES __declspec(empty_bases) +#else +#define SQLITE_ORM_MSVC_EMPTYBASES +#endif + +#if defined(_MSC_VER) && !defined(__clang__) // MSVC + +#if __cplusplus < 202002L +#define SQLITE_ORM_WORKAROUND_MSVC_MULTIPLECTOR_106654 +#endif + +#if _MSC_VER < 1920 #define SQLITE_ORM_BROKEN_VARIADIC_PACK_EXPANSION +#define SQLITE_ORM_BROKEN_CONSTEXPR_DELEGATING_CTORS +#endif + +#elif defined(__clang__) && defined(_MSC_VER) // Clang-cl (Clang for Windows) + +#elif defined(__clang__) // genuine Clang + +#elif defined(__clang__) && defined(__apple_build_version__) // Apple's Clang + +#elif defined(__GNUC__) // GCC + +#if __GNUC__ < 11 || (__GNUC__ == 11 && __GNUC_MINOR__ < 3) +#define SQLITE_ORM_BROKEN_GCC_ALIAS_TARGS_84785 +#endif + #endif namespace sqlite_orm { @@ -207,6 +248,30 @@ namespace sqlite_orm { using type_identity_t = typename type_identity::type; #endif +#if __cpp_lib_unwrap_ref >= 201811L + using std::unwrap_ref_decay, std::unwrap_ref_decay_t; + using std::unwrap_reference, std::unwrap_reference_t; +#else + template + struct unwrap_reference { + using type = T; + }; + template + struct unwrap_reference> { + using type = T&; + }; + template + using unwrap_reference_t = typename unwrap_reference::type; + + template + using unwrap_ref_decay_t = unwrap_reference_t>; + + template + struct unwrap_ref_decay { + using type = unwrap_ref_decay_t; + }; +#endif + #if 0 // __cpp_lib_detect >= 0L // library fundamentals TS v2, [meta.detect] using std::nonesuch; using std::detector; @@ -640,8 +705,7 @@ namespace sqlite_orm { #include // std::system_error #include // std::ostream #include // std::string -#include // std::tuple, std::make_tuple -#include // std::is_base_of, std::false_type, std::true_type +#include // std::is_base_of, std::false_type // #include "functional/cxx_universal.h" @@ -955,6 +1019,737 @@ namespace sqlite_orm { } } +// #include "functional/tuple.h" + +#include // std::integral_constant, std::decay, std::remove_reference, std::is_constructible, std::is_default_constructible, std::enable_if, std::declval +#include // std::move, std::forward +#include // std::equal_to + +// #include "cxx_universal.h" + +// #include "cxx_type_traits_polyfill.h" + +// #include "fast_and.h" + +// #include "cxx_universal.h" + +#ifndef SQLITE_ORM_BROKEN_VARIADIC_PACK_EXPANSION +#include +#else +// #include "cxx_type_traits_polyfill.h" + +#endif + +#ifndef SQLITE_ORM_BROKEN_VARIADIC_PACK_EXPANSION +namespace sqlite_orm { + namespace internal { + + template + struct fast_and : std::is_same, fast_and<(v, true)...>> {}; + } +} + +#define SQLITE_ORM_FAST_AND(...) ::sqlite_orm::internal::fast_and<__VA_ARGS__::value...>::value +#else +#define SQLITE_ORM_FAST_AND(...) polyfill::conjunction<__VA_ARGS__...>::value +#endif + +// #include "indexed_type.h" + +// #include "cxx_universal.h" + +namespace _sqlite_orm { + // short names defined in a short namespace to reduce symbol lengths, + // since those types are used as a building block; + // (as seen in boost hana) + + template + struct indexed_type { + using type = T; + }; +} + +namespace sqlite_orm { + namespace internal { + namespace mpl { + + using _sqlite_orm::indexed_type; + } + } +} + +// #include "index_sequence_util.h" + +#include // std::integral_constant, std::declval +#include // std::index_sequence, std::make_index_sequence + +// #include "cxx_universal.h" + +#ifdef SQLITE_ORM_RELAXED_CONSTEXPR_SUPPORTED +#include +#endif +// #include "pack.h" + +#include // std::integral_constant + +// #include "cxx_universal.h" + +namespace sqlite_orm { + namespace internal { + namespace mpl { + + /* + * Type list + */ + template + struct pack { + static constexpr size_t size() { + return sizeof...(T); + } + }; + } + } + + namespace mpl = internal::mpl; +} + +// retain stl tuple interface for `pack` +namespace std { + template + struct tuple_size; + + template + struct tuple_size> : integral_constant {}; +} + +namespace sqlite_orm { + namespace internal { + namespace mpl { + /** + * Get the first value of an index_sequence. + */ + template + SQLITE_ORM_CONSTEVAL size_t first_index_sequence_value(std::index_sequence) { + return I; + } + +#ifdef SQLITE_ORM_RELAXED_CONSTEXPR_SUPPORTED + /** + * Reorder the values of an index_sequence according to the positions from a second sequence. + */ + template + SQLITE_ORM_CONSTEVAL auto reorder_index_sequence(std::index_sequence, + std::index_sequence) { + constexpr std::array values{Value...}; + return std::index_sequence{}; + } + + template + SQLITE_ORM_CONSTEVAL std::index_sequence reorder_index_sequence(std::index_sequence, + std::index_sequence) { + return {}; + } + + inline SQLITE_ORM_CONSTEVAL std::index_sequence<> reorder_index_sequence(std::index_sequence<>, + std::index_sequence<>) { + return {}; + } + + /** + * Reverse the values of an index_sequence. + */ + template + SQLITE_ORM_CONSTEVAL auto reverse_index_sequence(std::index_sequence) { + return reorder_index_sequence(std::index_sequence{}, std::make_index_sequence{}); + } +#endif + +#ifdef SQLITE_ORM_BROKEN_VARIADIC_PACK_EXPANSION + template + using comma_expression_helper = std::integral_constant; +#endif + + /* + * Duplicate specified number x times into an index sequence (using the size of the variadic argument x) + */ + template + constexpr auto expand_n(std::index_sequence) { +#ifndef SQLITE_ORM_BROKEN_VARIADIC_PACK_EXPANSION + using type = std::index_sequence<(x, n)...>; +#else + using type = std::index_sequence::value...>; +#endif + return type{}; + } + + template + using expand_n_t = decltype(expand_n(Times{})); + +#if defined(SQLITE_ORM_BROKEN_VARIADIC_PACK_EXPANSION) || defined(SQLITE_ORM_BROKEN_GCC_ALIAS_TARGS_84785) + template + struct spread_idxseq_helper { + using type = expand_n_t>; + }; +#endif + + template + constexpr auto spread_idxseq(std::index_sequence, std::index_sequence) { +#if !defined(SQLITE_ORM_BROKEN_VARIADIC_PACK_EXPANSION) && !defined(SQLITE_ORM_BROKEN_GCC_ALIAS_TARGS_84785) + using type = pack>...>; +#else + using type = pack::type...>; +#endif + return type{}; + } + + template + using spread_idxseq_t = decltype(spread_idxseq(std::declval(), std::declval())); + + template + struct flatten_idxseq { + using type = std::index_sequence<>; + }; + + template + struct flatten_idxseq> { + using type = std::index_sequence; + }; + + template + struct flatten_idxseq, std::index_sequence, Seq...> + : flatten_idxseq, Seq...> {}; + + template + struct flatten_idxseq> : flatten_idxseq {}; + + template + using flatten_idxseq_t = typename flatten_idxseq::type; + } + } +} + +// #include "pack_util.h" + +// #include "pack.h" + +// #include "mpl.h" + +namespace sqlite_orm { + namespace internal { + namespace mpl { + + /* + * Flatten specified type lists into specified result type list + */ + template class R, class... List> + struct flatten_types { + using type = R<>; + }; + + template class R, template class List1, class... X> + struct flatten_types> { + using type = R; + }; + + template class R, + template + class List1, + template + class List2, + class... X, + class... Y, + class... List> + struct flatten_types, List2, List...> : flatten_types, List...> {}; + + template class R, class... List> + using flatten_types_t = typename flatten_types::type; + + template class R, class List, template class Op> + struct transform_types; + + template class R, template class List, class... X, template class Op> + struct transform_types, Op> { + using type = R...>; + }; + + /* + * Transform specified type list. + * + * `Op` is a metafunction operation. + */ + template class R, class List, template class Op> + using transform_types_t = typename transform_types::type; + } + } +} + +// #include "type_at.h" + +#include // std::integral_constant, std::index_sequence, std::make_index_sequence + +// #include "cxx_universal.h" + +// #include "indexed_type.h" + +// #include "pack.h" + +namespace sqlite_orm { + namespace internal { + namespace mpl { + +#ifndef SQLITE_ORM_HAS_TYPE_PACK_ELEMENT_INTRINSIC + template + struct indexer; + + template + struct indexer, T...> : indexed_type... {}; + + template + indexed_type get_indexed_type(const indexed_type&); +#endif + + template + struct type_at { +#ifdef SQLITE_ORM_HAS_TYPE_PACK_ELEMENT_INTRINSIC + using type = __type_pack_element; +#else + using Indexer = indexer, T...>; + // implementation note: needs to be aliased on its own [SQLITE_ORM_BROKEN_VARIADIC_PACK_EXPANSION] + using indexed_t = decltype(get_indexed_type(Indexer{})); + using type = typename indexed_t::type; +#endif + }; + + template + struct type_at> : type_at {}; + + template + using type_at_t = typename type_at::type; + + template + using element_at_t = typename type_at::type; + } + } + + namespace mpl = internal::mpl; +} + +// #include "tuple_common.h" + +#include // std::is_empty, std::is_final + +namespace _sqlite_orm { + template + constexpr bool is_ebo_able_v = std::is_empty::value && !std::is_final::value; +} + +namespace sqlite_orm { + namespace internal { + namespace mpl { + using _sqlite_orm::is_ebo_able_v; + + template + struct enable_tuple_variadic_ctor; + + template + struct enable_tuple_ctor; + + template + struct enable_tuple_nonconst_copy_ctor; + + struct from_variadic_t {}; + + template + struct remove_rvalue_reference { + using type = T; + }; + template + struct remove_rvalue_reference { + using type = T; + }; + template + using remove_rvalue_reference_t = typename remove_rvalue_reference::type; + +#ifdef SQLITE_ORM_BROKEN_VARIADIC_PACK_EXPANSION + template + struct make_idxseq_helper { + using type = std::make_index_sequence::value>; + }; +#endif + } + } + + namespace mpl = internal::mpl; +} + +namespace _sqlite_orm { + // short names defined in a short namespace to reduce symbol lengths, + // since those types are used as a building block; + // (as seen in boost hana) + + /* + * storage element of a tuple + */ + template::value && !std::is_final::value> + struct SQLITE_ORM_MSVC_EMPTYBASES tuplem : indexed_type { + X data; + + constexpr tuplem() : data() {} + + template + constexpr tuplem(Y&& y) : data(std::forward(y)) {} + }; + + /* + * storage element of a tuple, using EBO + */ + template + struct SQLITE_ORM_MSVC_EMPTYBASES tuplem : X, indexed_type { + + constexpr tuplem() = default; + + template + constexpr tuplem(Y&& y) : X(std::forward(y)) {} + }; + + template + constexpr const X& ebo_get(const tuplem& elem) { + return (elem.data); + } + template + constexpr X& ebo_get(tuplem& elem) { + return (elem.data); + } + template + constexpr X&& ebo_get(tuplem&& elem) { + return std::forward(elem.data); + } + template + constexpr const X& ebo_get(const tuplem& elem) { + return elem; + } + template + constexpr X& ebo_get(tuplem& elem) { + return elem; + } + template + constexpr X&& ebo_get(tuplem&& elem) { + return std::forward(elem); + } +} + +namespace sqlite_orm { + namespace internal { + namespace mpl { + using ::_sqlite_orm::ebo_get; + using ::_sqlite_orm::tuplem; + + template + struct basic_tuple; + + template + struct tuple; + + template + struct enable_tuple_ctor, Void...> + : std::enable_if), bool> {}; + + template + struct enable_tuple_ctor, Void...> + : std::enable_if), bool> {}; + + template + struct enable_tuple_variadic_ctor, Y...> + : std::enable_if), bool> {}; + +#ifdef SQLITE_ORM_WORKAROUND_MSVC_MULTIPLECTOR_106654 + template + struct enable_tuple_nonconst_copy_ctor, tuple, Void...> + : std::enable_if), bool> {}; + + template + struct enable_tuple_nonconst_copy_ctor, const tuple, Void...> + : std::enable_if), bool> {}; +#endif + } + } + + namespace mpl = internal::mpl; +} + +// retain stl tuple interface for `tuple` +namespace std { + template + struct tuple_size; + + template + struct tuple_element; + + template + struct tuple_size> : integral_constant {}; + + template + struct tuple_element> : sqlite_orm::mpl::type_at> { + }; + + template + constexpr decltype(auto) get(const sqlite_orm::mpl::tuple& tpl) noexcept { + using namespace sqlite_orm::mpl; + return ebo_get(tpl); + } + + template + constexpr decltype(auto) get(sqlite_orm::mpl::tuple& tpl) noexcept { + using namespace sqlite_orm::mpl; + return ebo_get(tpl); + } + + template + constexpr decltype(auto) get(sqlite_orm::mpl::tuple&& tpl) noexcept { + using namespace sqlite_orm::mpl; + return ebo_get(std::move(tpl)); + } + + template + decltype(auto) get(const sqlite_orm::mpl::tuple&) noexcept = delete; + + template + decltype(auto) get(sqlite_orm::mpl::tuple&) noexcept = delete; + + template + decltype(auto) get(sqlite_orm::mpl::tuple&&) noexcept = delete; +} + +namespace sqlite_orm { + namespace internal { + namespace mpl { + + template + struct SQLITE_ORM_MSVC_EMPTYBASES basic_tuple, X...> : tuplem... { + constexpr basic_tuple() = default; + + // variadic constructor + template + constexpr basic_tuple(from_variadic_t, Y&&... y) : tuplem(std::forward(y))... {} + + // converting copy/move constructor + template + constexpr basic_tuple(Other&& other) : tuplem(ebo_get(std::forward(other)))... {} + + // default copy constructor + constexpr basic_tuple(const basic_tuple&) = default; + // default move constructor + constexpr basic_tuple(basic_tuple&&) = default; + + // converting copy/move assignment + template + SQLITE_ORM_NONCONST_CONSTEXPR void operator=(Other&& other) { + int poormansfold[] = {(ebo_get(*this) = ebo_get(std::forward(other)), int{})...}; + (void)poormansfold; + } + + // default copy assignment + SQLITE_ORM_NONCONST_CONSTEXPR basic_tuple& operator=(const basic_tuple&) = default; + // default move assignment + SQLITE_ORM_NONCONST_CONSTEXPR basic_tuple& operator=(basic_tuple&&) = default; + }; + + template<> + struct tuple<> final { + constexpr tuple() = default; + }; + + /* + * tuple + */ + template + struct tuple final : basic_tuple, X...> { + using base_type = basic_tuple, X...>; + + // default constructor + template::type = true> + constexpr tuple() : base_type{} {} + + // direct constructor + template::type = true> + constexpr tuple(const X&... x) : base_type{from_variadic_t{}, x...} {} + + // converting constructor + template::type = true> + constexpr tuple(Y&&... y) : base_type{from_variadic_t{}, std::forward(y)...} {} + + // converting copy constructor + template), bool> = true> + constexpr tuple(const tuple& other) : base_type{other} {} + + // converting move constructor + template), bool> = true> + constexpr tuple(tuple&& other) : base_type{std::move(other)} {} + + // default copy constructor + constexpr tuple(const tuple&) = default; + // default move constructor + constexpr tuple(tuple&&) = default; + + // non-const copy constructor. + // The non-const copy constructor is required to make sure that + // the converting tuple(Y&&...) constructor is _not_ preferred over the copy + // constructor for unary tuples containing a type that is constructible from tuple<...>. +#ifndef SQLITE_ORM_WORKAROUND_MSVC_MULTIPLECTOR_106654 + constexpr tuple(tuple& other) : base_type{const_cast(other)} {} +#else + template::type = true> + constexpr tuple(Other& other) : base_type{const_cast(other)} {} +#endif + + // converting copy assignment + template), bool> = true> + SQLITE_ORM_NONCONST_CONSTEXPR tuple& operator=(const tuple& other) { + base_type::operator=(other); + return *this; + } + + // converting move assignment + template), bool> = true> + SQLITE_ORM_NONCONST_CONSTEXPR tuple& operator=(tuple&& other) { + base_type::operator=(std::move(other)); + return *this; + } + + // default copy assignment + SQLITE_ORM_NONCONST_CONSTEXPR tuple& operator=(const tuple&) = default; + // default move assignment + SQLITE_ORM_NONCONST_CONSTEXPR tuple& operator=(tuple&&) = default; + }; + + namespace adl { + template + constexpr auto make_tuple(X&&... x) { + return tuple...>{std::forward(x)...}; + } + + template + constexpr tuple forward_as_tuple(X&&... args) noexcept { + return {std::forward(args)...}; + } + + template + constexpr tuple tie(X&... args) noexcept { + return {args...}; + } + + template + constexpr flatten_types_t...> + tuple_cat_helper(std::index_sequence, std::index_sequence, Tuples&&... tuples) { + // Note that for each element in a tuple we have a coordinate pair (i, j), + // that is, the length of the lists containing the Is and the Js must be equal: + static_assert(sizeof...(Ix) == sizeof...(Jx), ""); + // It then explodes the tuple of tuples into the return type using the coordinates (i, j) for each element: + return {ebo_get(std::get(adl::forward_as_tuple(std::forward(tuples)...)))...}; + } + + /* + * This implementation of `tuple_cat` takes advantage of treating the specified tuples and + * their elements as a two-dimensional array. + * In order for this to work, the number of all elements combined (Jx) has to match + * a sequence of numbers produced using the number of specified tuples (Ix). + * Hence, each index in the sequence of tuples is duplicated by the number of elements of each respective tuple. + * + * Example, using 3 tuples: + * tuple0 + * tuple1 + * tuple0 + * + * outer sequence Jx (denoting which element to access): + * for tuple0: <0, 1, 2> + * for tuple1: <0> + * for tuple2: <0, 1> + * flattened -> <0, 1, 2, 0, 0, 1> + * + * inner sequence Ix (denoting which tuple to access): + * tuples as index sequence: <0, 1, 2> + * sizes as number sequence: <3, 1, 2> + * for tuple0: <0, 0, 0> + * for tuple1: <1> + * for tuple2: <2, 2> + * flattened -> <0, 0, 0, 1, 2, 2> + */ + template + constexpr auto tuple_cat(Tuples&&... tuples) { + using tuples_seq = std::make_index_sequence; + using sizes_seq = std::index_sequence>::value...>; + using inner = flatten_idxseq_t>; + using outer = typename flatten_idxseq< +#ifndef SQLITE_ORM_BROKEN_VARIADIC_PACK_EXPANSION + std::make_index_sequence>::value>... +#else + typename make_idxseq_helper>::type... +#endif + >::type; + + return tuple_cat_helper(inner{}, outer{}, std::forward(tuples)...); + } + } + using adl::forward_as_tuple; + using adl::make_tuple; + using adl::tie; + using adl::tuple_cat; + } + } +} + +// ops +namespace sqlite_orm { + namespace internal { + namespace mpl { + + // implementation note: we could derive from `type_at` but leverage the fact that `tuple` is derived from `indexed_type` + template + struct type_at> { + // implementation note: we could use `get_indexed_type()`, but `ebo_get` is readily available. + using forwarded_t = decltype(ebo_get(std::declval>())); + using type = remove_rvalue_reference_t; + }; + +#ifdef SQLITE_ORM_FOLD_EXPRESSIONS_SUPPORTED + template + constexpr bool equal_indexable([[maybe_unused]] const tuple& left, + [[maybe_unused]] const tuple& right, + std::index_sequence) { + constexpr std::equal_to<> predicate = {}; + return (predicate(ebo_get(left), ebo_get(right)) && ...); + } +#else + template + constexpr bool equal_indexable(const tuple&, const tuple&, std::index_sequence<>) { + return true; + } + template + constexpr bool + equal_indexable(const tuple& left, const tuple& right, std::index_sequence) { + return std::equal_to<>{}(ebo_get(left), ebo_get(right)) && + equal_indexable(left, right, std::index_sequence{}); + } +#endif + + template + constexpr bool operator==(const tuple& left, const tuple& right) { + static_assert(sizeof...(X) == sizeof...(Y), "cannot compare tuples of different sizes"); + return equal_indexable(left, right, std::make_index_sequence{}); + } + + template + constexpr bool operator!=(const tuple& left, const tuple& right) { + static_assert(sizeof...(X) == sizeof...(Y), "cannot compare tuples of different sizes"); + return !equal_indexable(left, right, std::make_index_sequence{}); + } + } + } +} + // #include "tuple_helper/same_or_void.h" namespace sqlite_orm { @@ -986,9 +1781,6 @@ namespace sqlite_orm { // #include "tuple_helper/tuple_traits.h" -#include // std::is_same -#include - // #include "../functional/cxx_type_traits_polyfill.h" // #include "../functional/mpl.h" @@ -1000,8 +1792,9 @@ namespace sqlite_orm { */ template class TraitFn, class Tuple> struct tuple_has {}; - template class TraitFn, class... Types> - struct tuple_has> : polyfill::disjunction...> {}; + + template class TraitFn, template class Tuple, class... Types> + struct tuple_has> : polyfill::disjunction...> {}; /* * Trait metafunction class that checks whether a tuple contains a type with given trait. @@ -1040,56 +1833,45 @@ namespace sqlite_orm { } // #include "tuple_helper/tuple_filter.h" -#include // std::integral_constant, std::index_sequence, std::conditional, std::declval -#include // std::tuple +#include // std::integral_constant, std::index_sequence, std::make_index_sequence, std::conditional, std::declval + +// #include "../functional/cxx_universal.h" + +// #include "../functional/index_sequence_util.h" + +// #include "../functional/pack_util.h" -// #include "../functional/cxx_universal.h" +// #include "../functional/tuple.h" namespace sqlite_orm { namespace internal { - template - using tuple_cat_t = decltype(std::tuple_cat(std::declval()...)); + template + using tuple_cat_t = mpl::flatten_types_t; template - struct conc_tuple { - using type = tuple_cat_t; - }; + struct conc_tuple : mpl::flatten_types {}; template struct tuple_from_index_sequence; - template - struct tuple_from_index_sequence> { - using type = std::tuple...>; + template class Tuple, class... T, size_t... Idx> + struct tuple_from_index_sequence, std::index_sequence> { + using type = Tuple>...>; }; template using tuple_from_index_sequence_t = typename tuple_from_index_sequence::type; - template - struct concat_idx_seq { - using type = std::index_sequence<>; - }; - - template - struct concat_idx_seq> { - using type = std::index_sequence; - }; - - template - struct concat_idx_seq, std::index_sequence, Seq...> - : concat_idx_seq, Seq...> {}; - template class Pred, template class Proj, class Seq> struct filter_tuple_sequence; #ifndef SQLITE_ORM_BROKEN_VARIADIC_PACK_EXPANSION template class Pred, template class Proj, size_t... Idx> struct filter_tuple_sequence> - : concat_idx_seq>>::value, - std::index_sequence, - std::index_sequence<>>...> {}; + : mpl::flatten_idxseq>>::value, + std::index_sequence, + std::index_sequence<>>...> {}; #else template class Pred, class SFINAE = void> struct tuple_seq_single { @@ -1103,7 +1885,7 @@ namespace sqlite_orm { template class Pred, template class Proj, size_t... Idx> struct filter_tuple_sequence> - : concat_idx_seq>, Pred>::type...> {}; + : mpl::flatten_idxseq>, Pred>::type...> {}; #endif template struct primary_key_t : primary_key_base { using order_by = primary_key_base::order_by; - using columns_tuple = std::tuple; + using columns_tuple = mpl::tuple; columns_tuple columns; - primary_key_t(decltype(columns) c) : columns(move(c)) {} + primary_key_t(decltype(columns) c) : columns(std::move(c)) {} primary_key_t asc() const { auto res = *this; @@ -1258,11 +2040,11 @@ namespace sqlite_orm { */ template struct unique_t : unique_base { - using columns_tuple = std::tuple; + using columns_tuple = mpl::tuple; columns_tuple columns; - unique_t(columns_tuple columns_) : columns(move(columns_)) {} + unique_t(columns_tuple columns_) : columns(std::move(columns_)) {} }; /** @@ -1411,9 +2193,9 @@ namespace sqlite_orm { } template - struct foreign_key_t, std::tuple> { - using columns_type = std::tuple; - using references_type = std::tuple; + struct foreign_key_t, mpl::tuple> { + using columns_type = mpl::tuple; + using references_type = mpl::tuple; using self = foreign_key_t; /** @@ -1437,7 +2219,7 @@ namespace sqlite_orm { static_assert(!std::is_same::value, "All references must have the same type"); foreign_key_t(columns_type columns_, references_type references_) : - columns(move(columns_)), references(move(references_)), + columns(std::move(columns_)), references(std::move(references_)), on_update(*this, true, foreign_key_action::none), on_delete(*this, false, foreign_key_action::none) {} foreign_key_t(const self& other) : @@ -1466,13 +2248,13 @@ namespace sqlite_orm { */ template struct foreign_key_intermediate_t { - using tuple_type = std::tuple; + using tuple_type = mpl::tuple; tuple_type columns; template - foreign_key_t, std::tuple> references(Rs... refs) { - return {std::move(this->columns), std::make_tuple(std::forward(refs)...)}; + foreign_key_t, mpl::tuple> references(Rs... refs) { + return {std::move(this->columns), mpl::make_tuple(std::forward(refs)...)}; } }; #endif @@ -1617,7 +2399,7 @@ namespace sqlite_orm { */ template internal::foreign_key_intermediate_t foreign_key(Cs... columns) { - return {std::make_tuple(std::forward(columns)...)}; + return {mpl::make_tuple(std::forward(columns)...)}; } #endif @@ -1626,7 +2408,7 @@ namespace sqlite_orm { */ template internal::unique_t unique(Args... args) { - return {std::make_tuple(std::forward(args)...)}; + return {mpl::make_tuple(std::forward(args)...)}; } inline internal::unique_t<> unique() { @@ -1639,7 +2421,7 @@ namespace sqlite_orm { template internal::primary_key_t primary_key(Cs... cs) { - return {std::make_tuple(std::forward(cs)...)}; + return {mpl::make_tuple(std::forward(cs)...)}; } inline internal::primary_key_t<> primary_key() { @@ -2011,7 +2793,6 @@ namespace sqlite_orm { } #pragma once -#include // std::tuple #include // std::string #include // std::unique_ptr #include // std::is_same, std::is_member_object_pointer @@ -2020,6 +2801,314 @@ namespace sqlite_orm { // #include "functional/cxx_type_traits_polyfill.h" +// #include "functional/fast_and.h" + +// #include "functional/unique_tuple.h" + +#include // std::integral_constant, std::decay, std::is_constructible, std::is_default_constructible, std::enable_if +#include // std::move, std::forward +#include // std::equal_to + +// #include "cxx_universal.h" + +// #include "cxx_type_traits_polyfill.h" + +// #include "fast_and.h" + +// #include "type_at.h" + +// #include "tuple_common.h" + +namespace _sqlite_orm { + // short names defined in a short namespace to reduce symbol lengths, + // since those types are used as a building block; + // (as seen in boost hana) + + /* + * storage element of a unique tuple + */ + template> + struct uplem { + X data; + + constexpr uplem() : data() {} + + template + constexpr uplem(Y&& y) : data(std::forward(y)) {} + }; + + /* + * storage element of a unique tuple, using EBO + */ + template + struct uplem : X { + + constexpr uplem() = default; + + template + constexpr uplem(Y&& y) : X(std::forward(y)) {} + }; + + template>> + constexpr const X& ebo_get(const uplem& elem) { + return (elem.data); + } + template, bool> = true> + constexpr X& ebo_get(uplem& elem) { + return (elem.data); + } + template, bool> = true> + constexpr X&& ebo_get(uplem&& elem) { + return std::forward(elem.data); + } + template, bool> = true> + constexpr const X& ebo_get(const uplem& elem) { + return elem; + } + template, bool> = true> + constexpr X& ebo_get(uplem& elem) { + return elem; + } + template, bool> = true> + constexpr X&& ebo_get(uplem&& elem) { + return std::forward(elem); + } +} + +namespace sqlite_orm { + namespace internal { + namespace mpl { + using ::_sqlite_orm::ebo_get; + using ::_sqlite_orm::uplem; + + template + struct uple; + + template + struct enable_tuple_ctor, Void...> + : std::enable_if), bool> {}; + + template + struct enable_tuple_ctor, Void...> + : std::enable_if), bool> {}; + + template + struct enable_tuple_variadic_ctor, Y...> + : std::enable_if), bool> {}; + +#ifdef SQLITE_ORM_WORKAROUND_MSVC_MULTIPLECTOR_106654 + template + struct enable_tuple_nonconst_copy_ctor, uple, Void...> + : std::enable_if), bool> {}; + + template + struct enable_tuple_nonconst_copy_ctor, const uple, Void...> + : std::enable_if), bool> {}; +#endif + } + } + + namespace mpl = internal::mpl; +} + +// retain stl tuple interface for `uple` +namespace std { + template + struct tuple_size; + + template + struct tuple_element; + + template + struct tuple_size> : integral_constant {}; + + template + struct tuple_element> : sqlite_orm::mpl::type_at> {}; + + template + constexpr decltype(auto) get(const sqlite_orm::mpl::uple& tpl) noexcept { + using namespace sqlite_orm::mpl; + using type = type_at_t; + return ebo_get(static_cast&>(tpl)); + } + + template + constexpr decltype(auto) get(sqlite_orm::mpl::uple& tpl) noexcept { + using namespace sqlite_orm::mpl; + using type = type_at_t; + return ebo_get(static_cast&>(tpl)); + } + + template + constexpr decltype(auto) get(sqlite_orm::mpl::uple&& tpl) noexcept { + using namespace sqlite_orm::mpl; + using type = type_at_t; + return ebo_get(static_cast&&>(tpl)); + } + + template + constexpr decltype(auto) get(const sqlite_orm::mpl::uple& tpl) noexcept { + using namespace sqlite_orm::mpl; + return ebo_get(static_cast&>(tpl)); + } + + template + constexpr decltype(auto) get(sqlite_orm::mpl::uple& tpl) noexcept { + using namespace sqlite_orm::mpl; + return ebo_get(static_cast&>(tpl)); + } + + template + constexpr decltype(auto) get(sqlite_orm::mpl::uple&& tpl) noexcept { + using namespace sqlite_orm::mpl; + return ebo_get(static_cast&&>(tpl)); + } +} + +namespace sqlite_orm { + namespace internal { + namespace mpl { + + template<> + struct uple<> final { + constexpr uple() = default; + }; + + /* + * unique tuple, which allows only distinct types. + */ + template + struct SQLITE_ORM_MSVC_EMPTYBASES uple final : uplem... { + // default constructor + template::type = true> + constexpr uple() {} + + // direct constructor + template::type = true> + constexpr uple(const X&... x) : uplem(x)... {} + + // converting constructor + template::type = true> + constexpr uple(Y&&... y) : uplem(std::forward(y))... {} + + // converting copy constructor + template), bool> = true> + constexpr uple(const uple& other) : uplem(ebo_get(other))... {} + + // converting move constructor + template), bool> = true> + constexpr uple(uple&& other) : uplem(ebo_get(std::move(other)))... {} + + // default copy constructor + constexpr uple(const uple&) = default; + // default move constructor + constexpr uple(uple&&) = default; + + // non-const copy constructor. + // The non-const copy constructor is required to make sure that + // the converting uple(Y&&...) constructor is _not_ preferred over the copy + // constructor for unary tuples containing a type that is constructible from uple<...>. +#ifndef SQLITE_ORM_WORKAROUND_MSVC_MULTIPLECTOR_106654 + constexpr uple(uple& other) : uplem(ebo_get(const_cast(other)))... {} +#else + template::type = true> + constexpr uple(Other& other) : uplem(ebo_get(const_cast(other)))... {} +#endif + + // converting copy assignment + template), bool> = true> + SQLITE_ORM_NONCONST_CONSTEXPR uple& operator=(const uple& other) { + int poormansfold[] = {(ebo_get(*this) = ebo_get(other), int{})...}; + (void)poormansfold; + return *this; + } + + // converting move assignment + template), bool> = true> + SQLITE_ORM_NONCONST_CONSTEXPR uple& operator=(uple&& other) { + int poormansfold[] = {(ebo_get(*this) = ebo_get(std::move(other)), int{})...}; + (void)poormansfold; + return *this; + } + + // default copy assignment + SQLITE_ORM_NONCONST_CONSTEXPR uple& operator=(const uple&) = default; + // default move assignment + SQLITE_ORM_NONCONST_CONSTEXPR uple& operator=(uple&&) = default; + }; + + template + constexpr auto make_unique_tuple(X&&... x) { + return uple...>{std::forward(x)...}; + } + + template + constexpr uple forward_as_unique_tuple(X&&... args) noexcept { + return {std::forward(args)...}; + } + + template + constexpr uple tie_unique(X&... args) noexcept { + return {args...}; + } + } + } +} + +// ops +namespace sqlite_orm { + namespace internal { + namespace mpl { + + template + struct type_at> : type_at {}; + +#ifdef SQLITE_ORM_FOLD_EXPRESSIONS_SUPPORTED + template = true> + constexpr bool equal_indexable([[maybe_unused]] const uple& left, + [[maybe_unused]] const uple& right, + std::index_sequence) { + return ((ebo_get(left) == ebo_get(right)) && ...); + } + + template = true> + constexpr bool equal_indexable([[maybe_unused]] const uple& left, + [[maybe_unused]] const uple& right, + std::index_sequence) { + constexpr std::equal_to<> predicate = {}; + return (predicate(std::get(left), std::get(right)) && ...); + } +#else + template + constexpr bool equal_indexable(const uple&, const uple&, std::index_sequence<>) { + return true; + } + template + constexpr bool + equal_indexable(const uple& left, const uple& right, std::index_sequence) { + return std::equal_to<>{}(std::get(left), std::get(right)) && + equal_indexable(left, right, std::index_sequence{}); + } +#endif + + template + constexpr bool operator==(const uple& left, const uple& right) { + static_assert(sizeof...(X) == sizeof...(Y), "cannot compare tuples of different sizes"); + return equal_indexable(left, right, std::make_index_sequence{}); + } + + template + constexpr bool operator!=(const uple& left, const uple& right) { + static_assert(sizeof...(X) == sizeof...(Y), "cannot compare tuples of different sizes"); + return !equal_indexable(left, right, std::make_index_sequence{}); + } + } + } +} + // #include "tuple_helper/tuple_traits.h" // #include "tuple_helper/tuple_filter.h" @@ -2157,13 +3246,12 @@ namespace sqlite_orm { * Member pointer used to read a field value. * If it is a object member pointer it is also used to write a field value. */ - const member_pointer_t member_pointer; + member_pointer_t member_pointer; /** * Setter member function to write a field value */ - SQLITE_ORM_NOUNIQUEADDRESS - const setter_type setter; + SQLITE_ORM_NOUNIQUEADDRESS const setter_type setter; /** * Simplified interface for `NOT NULL` constraint @@ -2180,10 +3268,9 @@ namespace sqlite_orm { */ template struct column_constraints { - using constraints_type = std::tuple; + using constraints_type = mpl::uple; - SQLITE_ORM_NOUNIQUEADDRESS - constraints_type constraints; + SQLITE_ORM_NOUNIQUEADDRESS constraints_type constraints; /** * Checks whether contraints are of trait `Trait` @@ -2216,9 +3303,9 @@ namespace sqlite_orm { template struct column_t : column_identifier, column_field, column_constraints { #ifndef SQLITE_ORM_AGGREGATE_BASES_SUPPORTED - column_t(std::string name, G memberPointer, S setter, std::tuple op) : + column_t(std::string name, G memberPointer, S setter, mpl::uple op) : column_identifier{move(name)}, column_field{memberPointer, setter}, column_constraints{ - move(op)} {} + std::move(op)} {} #endif }; @@ -2253,9 +3340,9 @@ namespace sqlite_orm { */ template = true> internal::column_t make_column(std::string name, M m, Op... constraints) { - static_assert(polyfill::conjunction_v...>, "Incorrect constraints pack"); + static_assert(SQLITE_ORM_FAST_AND(internal::is_constraint), "Incorrect constraints pack"); - SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES(return {move(name), m, {}, std::make_tuple(constraints...)}); + SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES(return {move(name), m, {}, mpl::make_unique_tuple(constraints...)}); } /** @@ -2269,9 +3356,10 @@ namespace sqlite_orm { internal::column_t make_column(std::string name, S setter, G getter, Op... constraints) { static_assert(std::is_same, internal::getter_field_type_t>::value, "Getter and setter must get and set same data type"); - static_assert(polyfill::conjunction_v...>, "Incorrect constraints pack"); + static_assert(SQLITE_ORM_FAST_AND(internal::is_constraint), "Incorrect constraints pack"); - SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES(return {move(name), getter, setter, std::make_tuple(constraints...)}); + SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES( + return {move(name), getter, setter, mpl::make_unique_tuple(constraints...)}); } /** @@ -2286,9 +3374,10 @@ namespace sqlite_orm { internal::column_t make_column(std::string name, G getter, S setter, Op... constraints) { static_assert(std::is_same, internal::getter_field_type_t>::value, "Getter and setter must get and set same data type"); - static_assert(polyfill::conjunction_v...>, "Incorrect constraints pack"); + static_assert(SQLITE_ORM_FAST_AND(internal::is_constraint), "Incorrect constraints pack"); - SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES(return {move(name), getter, setter, std::make_tuple(constraints...)}); + SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES( + return {move(name), getter, setter, mpl::make_unique_tuple(constraints...)}); } } #pragma once @@ -2457,13 +3546,17 @@ namespace sqlite_orm { #include // std::string #include // std::enable_if, std::is_same #include // std::vector -#include // std::tuple, std::tuple_size #include // std::stringstream +#include // std::move // #include "functional/cxx_universal.h" // #include "functional/cxx_type_traits_polyfill.h" +// #include "functional/pack.h" + +// #include "functional/tuple.h" + // #include "type_traits.h" // #include "collate_argument.h" @@ -2553,6 +3646,8 @@ namespace sqlite_orm { // #include "functional/cxx_universal.h" +// #include "functional/tuple.h" +// make_tuple // #include "operators.h" namespace sqlite_orm { @@ -2589,12 +3684,12 @@ namespace sqlite_orm { #endif template in_t in(Args... args) const { - return {this->value, std::make_tuple(std::forward(args)...), false}; + return {this->value, mpl::make_tuple(std::forward(args)...), false}; } template in_t not_in(Args... args) const { - return {this->value, std::make_tuple(std::forward(args)...), true}; + return {this->value, mpl::make_tuple(std::forward(args)...), true}; } template @@ -3007,7 +4102,7 @@ namespace sqlite_orm { template struct in_t : condition_t, in_base, negatable_t { L left; - std::tuple argument; + mpl::tuple argument; in_t(L left_, decltype(argument) argument_, bool negative_) : in_base{negative_}, left(std::move(left_)), argument(std::move(argument_)) {} @@ -3128,7 +4223,7 @@ namespace sqlite_orm { */ template struct multi_order_by_t : order_by_string { - using args_type = std::tuple; + using args_type = mpl::tuple; args_type args; @@ -3427,7 +4522,7 @@ namespace sqlite_orm { template struct from_t { - using tuple_type = std::tuple; + using pack_type = mpl::pack; }; template @@ -3440,7 +4535,7 @@ namespace sqlite_orm { */ template internal::from_t from() { - static_assert(std::tuple_size>::value > 0, ""); + static_assert(sizeof...(Args) > 0, ""); return {}; } @@ -3827,7 +4922,7 @@ namespace sqlite_orm { */ template internal::multi_order_by_t multi_order_by(Args&&... args) { - return {std::make_tuple(std::forward(args)...)}; + return {mpl::make_tuple(std::forward(args)...)}; } /** @@ -4168,13 +5263,14 @@ namespace sqlite_orm { #pragma once #include // std::string -#include // std::make_tuple, std::tuple_size #include // std::forward, std::is_base_of, std::enable_if #include // std::unique_ptr #include // std::vector // #include "functional/cxx_type_traits_polyfill.h" +// #include "functional/tuple.h" + // #include "conditions.h" // #include "is_base_of_template.h" @@ -4264,7 +5360,7 @@ namespace sqlite_orm { struct built_in_function_t : S, arithmetic_t { using return_type = R; using string_type = S; - using args_type = std::tuple; + using args_type = mpl::tuple; static constexpr size_t args_size = std::tuple_size::value; @@ -4892,7 +5988,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t acos(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -4908,7 +6004,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t acos(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -4920,7 +6016,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t acosh(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -4936,7 +6032,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t acosh(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -4948,7 +6044,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t asin(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -4964,7 +6060,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t asin(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -4976,7 +6072,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t asinh(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -4992,7 +6088,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t asinh(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -5004,7 +6100,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t atan(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -5020,7 +6116,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t atan(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -5032,7 +6128,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t atan2(X x, Y y) { - return {std::tuple{std::forward(x), std::forward(y)}}; + return {{std::forward(x), std::forward(y)}}; } /** @@ -5048,7 +6144,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t atan2(X x, Y y) { - return {std::tuple{std::forward(x), std::forward(y)}}; + return {{std::forward(x), std::forward(y)}}; } /** @@ -5060,7 +6156,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t atanh(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -5076,7 +6172,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t atanh(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -5088,7 +6184,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t ceil(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -5104,7 +6200,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t ceil(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -5116,7 +6212,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t ceiling(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -5132,7 +6228,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t ceiling(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -5144,7 +6240,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t cos(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -5160,7 +6256,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t cos(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -5172,7 +6268,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t cosh(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -5188,7 +6284,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t cosh(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -5200,7 +6296,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t degrees(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -5216,7 +6312,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t degrees(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -5228,7 +6324,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t exp(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -5244,7 +6340,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t exp(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -5256,7 +6352,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t floor(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -5272,7 +6368,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t floor(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -5284,7 +6380,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t ln(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -5300,7 +6396,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t ln(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -5312,7 +6408,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t log(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -5328,7 +6424,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t log(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -5340,7 +6436,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t log10(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -5356,7 +6452,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t log10(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -5368,7 +6464,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t log(B b, X x) { - return {std::tuple{std::forward(b), std::forward(x)}}; + return {{std::forward(b), std::forward(x)}}; } /** @@ -5384,7 +6480,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t log(B b, X x) { - return {std::tuple{std::forward(b), std::forward(x)}}; + return {{std::forward(b), std::forward(x)}}; } /** @@ -5396,7 +6492,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t log2(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -5412,7 +6508,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t log2(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -5424,7 +6520,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t mod_f(X x, Y y) { - return {std::tuple{std::forward(x), std::forward(y)}}; + return {{std::forward(x), std::forward(y)}}; } /** @@ -5440,7 +6536,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t mod_f(X x, Y y) { - return {std::tuple{std::forward(x), std::forward(y)}}; + return {{std::forward(x), std::forward(y)}}; } /** @@ -5479,7 +6575,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t pow(X x, Y y) { - return {std::tuple{std::forward(x), std::forward(y)}}; + return {{std::forward(x), std::forward(y)}}; } /** @@ -5495,7 +6591,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t pow(X x, Y y) { - return {std::tuple{std::forward(x), std::forward(y)}}; + return {{std::forward(x), std::forward(y)}}; } /** @@ -5507,7 +6603,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t power(X x, Y y) { - return {std::tuple{std::forward(x), std::forward(y)}}; + return {{std::forward(x), std::forward(y)}}; } /** @@ -5523,7 +6619,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t power(X x, Y y) { - return {std::tuple{std::forward(x), std::forward(y)}}; + return {{std::forward(x), std::forward(y)}}; } /** @@ -5535,7 +6631,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t radians(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -5551,7 +6647,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t radians(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -5563,7 +6659,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t sin(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -5579,7 +6675,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t sin(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -5591,7 +6687,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t sinh(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -5607,7 +6703,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t sinh(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -5619,7 +6715,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t sqrt(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -5635,7 +6731,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t sqrt(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -5647,7 +6743,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t tan(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -5663,7 +6759,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t tan(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -5675,7 +6771,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t tanh(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -5691,7 +6787,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t tanh(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -5703,7 +6799,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t trunc(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -5719,7 +6815,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t trunc(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } #endif // SQLITE_ENABLE_MATH_FUNCTIONS /** @@ -5727,7 +6823,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t typeof_(T t) { - return {std::tuple{std::forward(t)}}; + return {{std::forward(t)}}; } /** @@ -5735,7 +6831,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t unicode(T t) { - return {std::tuple{std::forward(t)}}; + return {{std::forward(t)}}; } /** @@ -5743,7 +6839,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t length(T t) { - return {std::tuple{std::forward(t)}}; + return {{std::forward(t)}}; } /** @@ -5751,7 +6847,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t, internal::abs_string, T> abs(T t) { - return {std::tuple{std::forward(t)}}; + return {{std::forward(t)}}; } /** @@ -5759,7 +6855,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t lower(T t) { - return {std::tuple{std::forward(t)}}; + return {{std::forward(t)}}; } /** @@ -5767,7 +6863,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t upper(T t) { - return {std::tuple{std::forward(t)}}; + return {{std::forward(t)}}; } /** @@ -5796,7 +6892,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t trim(T t) { - return {std::tuple{std::forward(t)}}; + return {{std::forward(t)}}; } /** @@ -5804,7 +6900,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t trim(X x, Y y) { - return {std::tuple{std::forward(x), std::forward(y)}}; + return {{std::forward(x), std::forward(y)}}; } /** @@ -5812,7 +6908,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t ltrim(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -5820,7 +6916,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t ltrim(X x, Y y) { - return {std::tuple{std::forward(x), std::forward(y)}}; + return {{std::forward(x), std::forward(y)}}; } /** @@ -5828,7 +6924,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t rtrim(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -5836,7 +6932,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t rtrim(X x, Y y) { - return {std::tuple{std::forward(x), std::forward(y)}}; + return {{std::forward(x), std::forward(y)}}; } /** @@ -5844,7 +6940,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t hex(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -5852,7 +6948,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t quote(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -5860,7 +6956,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t, internal::randomblob_string, X> randomblob(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -5868,7 +6964,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t instr(X x, Y y) { - return {std::tuple{std::forward(x), std::forward(y)}}; + return {{std::forward(x), std::forward(y)}}; } /** @@ -5877,9 +6973,9 @@ namespace sqlite_orm { template, internal::is_into>::value == 0, bool> = true> + std::enable_if_t, internal::is_into>::value == 0, bool> = true> internal::built_in_function_t replace(X x, Y y, Z z) { - return {std::tuple{std::forward(x), std::forward(y), std::forward(z)}}; + return {{std::forward(x), std::forward(y), std::forward(z)}}; } /** @@ -5887,7 +6983,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t round(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -5895,7 +6991,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t round(X x, Y y) { - return {std::tuple{std::forward(x), std::forward(y)}}; + return {{std::forward(x), std::forward(y)}}; } #if SQLITE_VERSION_NUMBER >= 3007016 @@ -5905,7 +7001,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t char_(Args... args) { - return {std::make_tuple(std::forward(args)...)}; + return {{std::forward(args)...}}; } /** @@ -5928,7 +7024,7 @@ namespace sqlite_orm { polyfill::type_identity>::type, internal::coalesce_string, Args...> { - return {std::make_tuple(std::forward(args)...)}; + return {{std::forward(args)...}}; } /** @@ -5943,7 +7039,7 @@ namespace sqlite_orm { internal::ifnull_string, X, Y> { - return {std::make_tuple(std::move(x), std::move(y))}; + return {{std::move(x), std::move(y)}}; } /** @@ -5969,17 +7065,17 @@ namespace sqlite_orm { X, Y>; - return F{std::make_tuple(std::move(x), std::move(y))}; + return F{{std::move(x), std::move(y)}}; } else { using F = internal::built_in_function_t; - return F{std::make_tuple(std::move(x), std::move(y))}; + return F{{std::move(x), std::move(y)}}; } } #else template internal::built_in_function_t nullif(X x, Y y) { - return {std::make_tuple(std::move(x), std::move(y))}; + return {{std::move(x), std::move(y)}}; } #endif @@ -5988,7 +7084,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t date(Args... args) { - return {std::tuple{std::forward(args)...}}; + return {{std::forward(args)...}}; } /** @@ -5996,7 +7092,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t time(Args... args) { - return {std::tuple{std::forward(args)...}}; + return {{std::forward(args)...}}; } /** @@ -6004,7 +7100,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t datetime(Args... args) { - return {std::tuple{std::forward(args)...}}; + return {{std::forward(args)...}}; } /** @@ -6012,7 +7108,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t julianday(Args... args) { - return {std::tuple{std::forward(args)...}}; + return {{std::forward(args)...}}; } /** @@ -6020,7 +7116,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t strftime(Args... args) { - return {std::tuple{std::forward(args)...}}; + return {{std::forward(args)...}}; } /** @@ -6028,7 +7124,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t, internal::zeroblob_string, N> zeroblob(N n) { - return {std::tuple{std::forward(n)}}; + return {{std::forward(n)}}; } /** @@ -6036,7 +7132,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t substr(X x, Y y) { - return {std::tuple{std::forward(x), std::forward(y)}}; + return {{std::forward(x), std::forward(y)}}; } /** @@ -6044,7 +7140,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t substr(X x, Y y, Z z) { - return {std::tuple{std::forward(x), std::forward(y), std::forward(z)}}; + return {{std::forward(x), std::forward(y), std::forward(z)}}; } #ifdef SQLITE_SOUNDEX @@ -6053,7 +7149,7 @@ namespace sqlite_orm { */ template internal::built_in_function_t soundex(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } #endif @@ -6062,7 +7158,7 @@ namespace sqlite_orm { */ template internal::built_in_aggregate_function_t total(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -6070,7 +7166,7 @@ namespace sqlite_orm { */ template internal::built_in_aggregate_function_t, internal::sum_string, X> sum(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -6078,7 +7174,7 @@ namespace sqlite_orm { */ template internal::built_in_aggregate_function_t count(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -6102,7 +7198,7 @@ namespace sqlite_orm { */ template internal::built_in_aggregate_function_t avg(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -6110,7 +7206,7 @@ namespace sqlite_orm { */ template internal::built_in_aggregate_function_t, internal::max_string, X> max(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -6118,7 +7214,7 @@ namespace sqlite_orm { */ template internal::built_in_aggregate_function_t, internal::min_string, X> min(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -6128,7 +7224,7 @@ namespace sqlite_orm { template internal::built_in_function_t, internal::max_string, X, Y, Rest...> max(X x, Y y, Rest... rest) { - return {std::tuple{std::forward(x), std::forward(y), std::forward(rest)...}}; + return {{std::forward(x), std::forward(y), std::forward(rest)...}}; } /** @@ -6138,7 +7234,7 @@ namespace sqlite_orm { template internal::built_in_function_t, internal::min_string, X, Y, Rest...> min(X x, Y y, Rest... rest) { - return {std::tuple{std::forward(x), std::forward(y), std::forward(rest)...}}; + return {{std::forward(x), std::forward(y), std::forward(rest)...}}; } /** @@ -6146,7 +7242,7 @@ namespace sqlite_orm { */ template internal::built_in_aggregate_function_t group_concat(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } /** @@ -6154,128 +7250,124 @@ namespace sqlite_orm { */ template internal::built_in_aggregate_function_t group_concat(X x, Y y) { - return {std::tuple{std::forward(x), std::forward(y)}}; + return {{std::forward(x), std::forward(y)}}; } #ifdef SQLITE_ENABLE_JSON1 template internal::built_in_function_t json(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } template internal::built_in_function_t json_array(Args... args) { - return {std::tuple{std::forward(args)...}}; + return {{std::forward(args)...}}; } template internal::built_in_function_t json_array_length(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } template internal::built_in_function_t json_array_length(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } template internal::built_in_function_t json_array_length(X x, Y y) { - return {std::tuple{std::forward(x), std::forward(y)}}; + return {{std::forward(x), std::forward(y)}}; } template internal::built_in_function_t json_array_length(X x, Y y) { - return {std::tuple{std::forward(x), std::forward(y)}}; + return {{std::forward(x), std::forward(y)}}; } template internal::built_in_function_t json_extract(X x, Args... args) { - return {std::tuple{std::forward(x), std::forward(args)...}}; + return {{std::forward(x), std::forward(args)...}}; } template internal::built_in_function_t json_insert(X x, Args... args) { - static_assert(std::tuple_size>::value % 2 == 0, - "number of arguments in json_insert must be odd"); - return {std::tuple{std::forward(x), std::forward(args)...}}; + static_assert(sizeof...(Args) % 2 == 0, "number of arguments in json_insert must be odd"); + return {{std::forward(x), std::forward(args)...}}; } template internal::built_in_function_t json_replace(X x, Args... args) { - static_assert(std::tuple_size>::value % 2 == 0, - "number of arguments in json_replace must be odd"); - return {std::tuple{std::forward(x), std::forward(args)...}}; + static_assert(sizeof...(Args) % 2 == 0, "number of arguments in json_replace must be odd"); + return {{std::forward(x), std::forward(args)...}}; } template internal::built_in_function_t json_set(X x, Args... args) { - static_assert(std::tuple_size>::value % 2 == 0, - "number of arguments in json_set must be odd"); - return {std::tuple{std::forward(x), std::forward(args)...}}; + static_assert(sizeof...(Args) % 2 == 0, "number of arguments in json_set must be odd"); + return {{std::forward(x), std::forward(args)...}}; } template internal::built_in_function_t json_object(Args... args) { - static_assert(std::tuple_size>::value % 2 == 0, - "number of arguments in json_object must be even"); - return {std::tuple{std::forward(args)...}}; + static_assert(sizeof...(Args) % 2 == 0, "number of arguments in json_object must be even"); + return {{std::forward(args)...}}; } template internal::built_in_function_t json_patch(X x, Y y) { - return {std::tuple{std::forward(x), std::forward(y)}}; + return {{std::forward(x), std::forward(y)}}; } template internal::built_in_function_t json_remove(X x, Args... args) { - return {std::tuple{std::forward(x), std::forward(args)...}}; + return {{std::forward(x), std::forward(args)...}}; } template internal::built_in_function_t json_remove(X x, Args... args) { - return {std::tuple{std::forward(x), std::forward(args)...}}; + return {{std::forward(x), std::forward(args)...}}; } template internal::built_in_function_t json_type(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } template internal::built_in_function_t json_type(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } template internal::built_in_function_t json_type(X x, Y y) { - return {std::tuple{std::forward(x), std::forward(y)}}; + return {{std::forward(x), std::forward(y)}}; } template internal::built_in_function_t json_type(X x, Y y) { - return {std::tuple{std::forward(x), std::forward(y)}}; + return {{std::forward(x), std::forward(y)}}; } template internal::built_in_function_t json_valid(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } template internal::built_in_function_t json_quote(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } template internal::built_in_function_t json_group_array(X x) { - return {std::tuple{std::forward(x)}}; + return {{std::forward(x)}}; } template internal::built_in_function_t json_group_object(X x, Y y) { - return {std::tuple{std::forward(x), std::forward(y)}}; + return {{std::forward(x), std::forward(y)}}; } #endif // SQLITE_ENABLE_JSON1 @@ -6351,6 +7443,8 @@ namespace sqlite_orm { // #include "functional/cxx_type_traits_polyfill.h" +// #include "functional/tuple.h" + // #include "is_base_of_template.h" // #include "tuple_helper/tuple_filter.h" @@ -6415,18 +7509,18 @@ namespace sqlite_orm { // #include "ast/group_by.h" -#include // std::tuple, std::make_tuple -#include // std::true_type, std::false_type #include // std::forward, std::move // #include "../functional/cxx_type_traits_polyfill.h" +// #include "../functional/tuple.h" + namespace sqlite_orm { namespace internal { template struct group_by_with_having { - using args_type = std::tuple; + using args_type = mpl::tuple; using expression_type = T; args_type args; @@ -6438,7 +7532,7 @@ namespace sqlite_orm { */ template struct group_by_t { - using args_type = std::tuple; + using args_type = mpl::tuple; args_type args; @@ -6473,7 +7567,7 @@ namespace sqlite_orm { */ template internal::group_by_t group_by(Args&&... args) { - return {std::make_tuple(std::forward(args)...)}; + return {mpl::make_tuple(std::forward(args)...)}; } /** @@ -6538,7 +7632,7 @@ namespace sqlite_orm { template struct columns_t { - using columns_type = std::tuple; + using columns_type = mpl::tuple; columns_type columns; bool distinct = false; @@ -6546,7 +7640,7 @@ namespace sqlite_orm { static constexpr int count = std::tuple_size::value; #ifndef SQLITE_ORM_AGGREGATE_NSDMI_SUPPORTED - columns_t(columns_type columns) : columns{move(columns)} {} + columns_t(columns_type columns) : columns{std::move(columns)} {} #endif }; @@ -6558,7 +7652,7 @@ namespace sqlite_orm { template struct set_t { - using assigns_type = std::tuple; + using assigns_type = mpl::tuple; assigns_type assigns; }; @@ -6612,14 +7706,15 @@ namespace sqlite_orm { template struct select_t { using return_type = T; - using conditions_type = std::tuple; + using conditions_type = mpl::tuple; return_type col; conditions_type conditions; bool highest_level = false; #ifndef SQLITE_ORM_AGGREGATE_NSDMI_SUPPORTED - select_t(return_type col, conditions_type conditions) : col{std::move(col)}, conditions{move(conditions)} {} + select_t(return_type col, conditions_type conditions) : + col{std::move(col)}, conditions{std::move(conditions)} {} #endif }; @@ -6757,7 +7852,7 @@ namespace sqlite_orm { struct simple_case_t { using return_type = R; using case_expression_type = T; - using args_type = std::tuple; + using args_type = mpl::tuple; using else_expression_type = E; optional_container case_expression; @@ -6774,7 +7869,7 @@ namespace sqlite_orm { struct simple_case_builder { using return_type = R; using case_expression_type = T; - using args_type = std::tuple; + using args_type = mpl::tuple; using else_expression_type = E; optional_container case_expression; @@ -6783,9 +7878,9 @@ namespace sqlite_orm { template simple_case_builder> when(W w, then_t t) { - using result_args_type = std::tuple>; + using result_args_type = mpl::tuple>; std::pair newPair{std::move(w), std::move(t.expression)}; - result_args_type result_args = std::tuple_cat(std::move(this->args), std::make_tuple(newPair)); + result_args_type result_args = mpl::tuple_cat(std::move(this->args), mpl::make_tuple(newPair)); std::get::value - 1>(result_args) = std::move(newPair); return {std::move(this->case_expression), std::move(result_args), std::move(this->else_expression)}; } @@ -6853,16 +7948,16 @@ namespace sqlite_orm { */ template internal::set_t set(Args... args) { - using arg_tuple = std::tuple; - static_assert(std::tuple_size::value == - internal::count_tuple::value, + using args_pack = mpl::pack; + static_assert(std::tuple_size::value == + internal::count_tuple::value, "set function accepts assign operators only"); - return {std::make_tuple(std::forward(args)...)}; + return {mpl::make_tuple(std::forward(args)...)}; } template internal::columns_t columns(Args... args) { - return {std::make_tuple(std::forward(args)...)}; + return {mpl::make_tuple(std::forward(args)...)}; } /** @@ -6880,9 +7975,9 @@ namespace sqlite_orm { */ template internal::select_t select(T t, Args... args) { - using args_tuple = std::tuple; + using args_tuple = mpl::pack; internal::validate_conditions(); - return {std::move(t), std::make_tuple(std::forward(args)...)}; + return {std::move(t), mpl::make_tuple(std::forward(args)...)}; } /** @@ -7013,13 +8108,13 @@ namespace sqlite_orm { } #pragma once -#include -#include #include -#include +#include // std::move, std::forward // #include "functional/cxx_universal.h" +// #include "functional/tuple.h" + // #include "optional_container.h" // NOTE Idea : Maybe also implement a custom trigger system to call a c++ callback when a trigger triggers ? @@ -7040,7 +8135,7 @@ namespace sqlite_orm { */ template struct partial_trigger_t { - using statements_type = std::tuple; + using statements_type = mpl::tuple; /** * Base of the trigger (contains its type, timing and associated table) @@ -7052,7 +8147,7 @@ namespace sqlite_orm { statements_type statements; partial_trigger_t(T trigger_base, S... statements) : - base{std::move(trigger_base)}, statements{std::make_tuple(std::forward(statements)...)} {} + base{std::move(trigger_base)}, statements{mpl::make_tuple(std::forward(statements)...)} {} partial_trigger_t& end() { return *this; @@ -7170,7 +8265,7 @@ namespace sqlite_orm { */ template struct trigger_update_type_t : trigger_type_base_t { - using columns_type = std::tuple; + using columns_type = mpl::tuple; /** * Contains the columns the trigger is watching. Will only @@ -7179,7 +8274,7 @@ namespace sqlite_orm { columns_type columns; trigger_update_type_t(trigger_timing timing, trigger_type type, Cs... columns) : - trigger_type_base_t(timing, type), columns(std::make_tuple(std::forward(columns)...)) {} + trigger_type_base_t(timing, type), columns(mpl::make_tuple(std::forward(columns)...)) {} template trigger_base_t> on() { @@ -7644,8 +8739,7 @@ namespace sqlite_orm { class pointer_binding { P* p_; - SQLITE_ORM_NOUNIQUEADDRESS - D d_; + SQLITE_ORM_NOUNIQUEADDRESS D d_; protected: // Constructing pointer bindings must go through bindable_pointer() @@ -8214,7 +9308,7 @@ namespace sqlite_orm { #include #include // std::copy #include // std::back_inserter -#include // std::tuple, std::tuple_size, std::tuple_element +#include // std::tuple // #include "functional/cxx_universal.h" @@ -8809,12 +9903,14 @@ namespace sqlite_orm { } #pragma once -#include // std::tuple, std::make_tuple, std::declval +#include // std::declval #include // std::string #include // std::forward // #include "functional/cxx_universal.h" +// #include "functional/tuple.h" + // #include "tuple_helper/tuple_filter.h" // #include "indexed_column.h" @@ -8904,12 +10000,12 @@ namespace sqlite_orm { template struct index_t : index_base { - using elements_type = std::tuple; + using elements_type = mpl::tuple; using object_type = void; #ifndef SQLITE_ORM_AGGREGATE_BASES_SUPPORTED index_t(std::string name_, bool unique_, elements_type elements_) : - index_base{move(name_), unique_}, elements(move(elements_)) {} + index_base{move(name_), unique_}, elements(std::move(elements_)) {} #endif elements_type elements; @@ -8919,21 +10015,19 @@ namespace sqlite_orm { template internal::index_t()))...> make_index(std::string name, Cols... cols) { - using cols_tuple = std::tuple; - static_assert(internal::count_tuple::value <= 1, + static_assert(internal::count_tuple, internal::is_where>::value <= 1, "amount of where arguments can be 0 or 1"); SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES( - return {move(name), false, std::make_tuple(internal::make_indexed_column(std::move(cols))...)}); + return {move(name), false, mpl::make_tuple(internal::make_indexed_column(std::move(cols))...)}); } template internal::index_t()))...> make_unique_index(std::string name, Cols... cols) { - using cols_tuple = std::tuple; - static_assert(internal::count_tuple::value <= 1, + static_assert(internal::count_tuple, internal::is_where>::value <= 1, "amount of where arguments can be 0 or 1"); SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES( - return {move(name), true, std::make_tuple(internal::make_indexed_column(std::move(cols))...)}); + return {move(name), true, mpl::make_tuple(internal::make_indexed_column(std::move(cols))...)}); } } #pragma once @@ -9067,18 +10161,13 @@ namespace sqlite_orm { #include // std::tuple -// #include "../functional/mpl.h" +// #include "../functional/pack_util.h" namespace sqlite_orm { namespace internal { template class Op> - struct tuple_transformer; - - template class Op> - struct tuple_transformer, Op> { - using type = std::tuple...>; - }; + struct tuple_transformer : mpl::transform_types {}; /* * Transform specified tuple. @@ -9086,7 +10175,7 @@ namespace sqlite_orm { * `Op` is a metafunction operation. */ template class Op> - using transform_tuple_t = typename tuple_transformer::type; + using transform_tuple_t = mpl::transform_types_t; } } @@ -9095,12 +10184,13 @@ namespace sqlite_orm { // #include "storage_lookup.h" #include // std::true_type, std::false_type, std::remove_const, std::enable_if -#include // #include "functional/cxx_universal.h" // #include "functional/cxx_type_traits_polyfill.h" +// #include "functional/unique_tuple.h" + // #include "type_traits.h" namespace sqlite_orm { @@ -9110,7 +10200,7 @@ namespace sqlite_orm { struct storage_t; template - using db_objects_tuple = std::tuple; + using db_objects_tuple = mpl::uple; template struct is_storage : std::false_type {}; @@ -9161,7 +10251,7 @@ namespace sqlite_orm { struct storage_pick_table> : storage_pick_table {}; #else template - struct storage_pick_table> : storage_pick_table {}; + struct storage_pick_table> : storage_pick_table {}; #endif /** @@ -9188,7 +10278,7 @@ namespace sqlite_orm { struct storage_find_table> : storage_find_table {}; #else template - struct storage_find_table> : storage_find_table {}; + struct storage_find_table> : storage_find_table {}; #endif /** @@ -9262,7 +10352,6 @@ namespace sqlite_orm { #include #include #include // std::string -#include // std::tuple #include // std::function #include // std::min #include // std::move, std::forward @@ -9271,6 +10360,10 @@ namespace sqlite_orm { // #include "functional/cxx_type_traits_polyfill.h" +// #include "functional/type_at.h" + +// #include "functional/tuple.h" + namespace sqlite_orm { struct arg_values; @@ -9360,14 +10453,14 @@ namespace sqlite_orm { template struct member_function_arguments { using member_function_type = R (O::*)(Args...) const; - using tuple_type = std::tuple...>; + using tuple_type = mpl::tuple...>; using return_type = R; }; template struct member_function_arguments { using member_function_type = R (O::*)(Args...); - using tuple_type = std::tuple...>; + using tuple_type = mpl::tuple...>; using return_type = R; }; @@ -9392,7 +10485,7 @@ namespace sqlite_orm { template struct function_call { using function_type = F; - using args_tuple = std::tuple; + using args_tuple = mpl::tuple; args_tuple args; }; @@ -9463,13 +10556,13 @@ namespace sqlite_orm { } template SQLITE_ORM_CONSTEVAL bool validate_pointer_value_types(polyfill::index_constant) { - using func_arg_t = std::tuple_element_t; - using passed_arg_t = unpacked_arg_t>; + using func_arg_t = mpl::element_at_t; + using passed_arg_t = unpacked_arg_t>; #ifdef SQLITE_ORM_RELAXED_CONSTEXPR_SUPPORTED constexpr bool valid = validate_pointer_value_type, - unpacked_arg_t>>( + mpl::element_at_t, + unpacked_arg_t>>( polyfill::bool_constant < (polyfill::is_specialization_of_v) || (polyfill::is_specialization_of_v) > {}); @@ -9477,8 +10570,8 @@ namespace sqlite_orm { #else return validate_pointer_value_types(polyfill::index_constant{}) && validate_pointer_value_type, - unpacked_arg_t>>( + mpl::element_at_t, + unpacked_arg_t>>( polyfill::bool_constant < (polyfill::is_specialization_of_v) || (polyfill::is_specialization_of_v) > {}); #endif @@ -9490,17 +10583,18 @@ namespace sqlite_orm { */ template internal::function_call func(Args... args) { - using args_tuple = std::tuple; - using function_args_tuple = typename internal::callable_arguments::args_tuple; - constexpr auto argsCount = std::tuple_size::value; + using namespace internal; + using args_pack = mpl::pack; + using function_args_tuple = typename callable_arguments::args_tuple; + constexpr auto argsCount = args_pack::size(); constexpr auto functionArgsCount = std::tuple_size::value; static_assert((argsCount == functionArgsCount && - !std::is_same>::value && - internal::validate_pointer_value_types( + !std::is_same>::value && + internal::validate_pointer_value_types, args_pack>( polyfill::index_constant(functionArgsCount, argsCount) - 1>{})) || - std::is_same>::value, + std::is_same>::value, "Number of arguments does not match"); - return {std::make_tuple(std::forward(args)...)}; + return {mpl::make_tuple(std::forward(args)...)}; } } @@ -9780,7 +10874,6 @@ namespace sqlite_orm { #include // std::string #include // std::remove_reference, std::is_same, std::decay #include // std::vector -#include // std::tuple_size, std::tuple_element #include // std::forward, std::move // #include "functional/cxx_universal.h" @@ -9865,60 +10958,13 @@ namespace sqlite_orm { // #include "functional/mpl.h" -// #include "typed_comparator.h" - -// #include "tuple_helper/index_sequence_util.h" - -#include // std::index_sequence, std::make_index_sequence - -// #include "../functional/cxx_universal.h" - -#ifdef SQLITE_ORM_RELAXED_CONSTEXPR_SUPPORTED -#include -#endif - -namespace sqlite_orm { - namespace internal { - /** - * Get the first value of an index_sequence. - */ - template - SQLITE_ORM_CONSTEVAL size_t first_index_sequence_value(std::index_sequence) { - return I; - } - -#ifdef SQLITE_ORM_RELAXED_CONSTEXPR_SUPPORTED - /** - * Reorder the values of an index_sequence according to the positions from a second sequence. - */ - template - SQLITE_ORM_CONSTEVAL auto reorder_index_sequence(std::index_sequence, - std::index_sequence) { - constexpr std::array values{Value...}; - return std::index_sequence{}; - } +// #include "functional/type_at.h" - template - SQLITE_ORM_CONSTEVAL std::index_sequence reorder_index_sequence(std::index_sequence, - std::index_sequence) { - return {}; - } +// #include "functional/index_sequence_util.h" - inline SQLITE_ORM_CONSTEVAL std::index_sequence<> reorder_index_sequence(std::index_sequence<>, - std::index_sequence<>) { - return {}; - } +// #include "functional/tuple.h" - /** - * Reverse the values of an index_sequence. - */ - template - SQLITE_ORM_CONSTEVAL auto reverse_index_sequence(std::index_sequence) { - return reorder_index_sequence(std::index_sequence{}, std::make_index_sequence{}); - } -#endif - } -} +// #include "typed_comparator.h" // #include "tuple_helper/tuple_filter.h" @@ -9926,7 +10972,6 @@ namespace sqlite_orm { // #include "tuple_helper/tuple_iteration.h" -#include // std::tuple, std::get, std::tuple_element, std::tuple_size #include // std::index_sequence, std::make_index_sequence #include // std::forward, std::move @@ -9936,53 +10981,60 @@ namespace sqlite_orm { // #include "../functional/cxx_functional_polyfill.h" -// #include "index_sequence_util.h" +// #include "../functional/index_sequence_util.h" namespace sqlite_orm { namespace internal { + namespace mpl { + template + struct pack; + + template + struct uple; + } // got it form here https://stackoverflow.com/questions/7858817/unpacking-a-tuple-to-call-a-matching-function-pointer template auto call_impl(Function& f, FunctionPointer functionPointer, Tuple t, std::index_sequence) { - return (f.*functionPointer)(std::get(move(t))...); + return (f.*functionPointer)(std::get(std::move(t))...); } template auto call(Function& f, FunctionPointer functionPointer, Tuple t) { constexpr size_t size = std::tuple_size::value; - return call_impl(f, functionPointer, move(t), std::make_index_sequence{}); + return call_impl(f, functionPointer, std::move(t), std::make_index_sequence{}); } template auto call(Function& f, Tuple t) { - return call(f, &Function::operator(), move(t)); + return call(f, &Function::operator(), std::move(t)); } #if defined(SQLITE_ORM_FOLD_EXPRESSIONS_SUPPORTED) && defined(SQLITE_ORM_IF_CONSTEXPR_SUPPORTED) - template - void iterate_tuple(const Tpl& tpl, std::index_sequence, L&& lambda) { + template + void iterate_tuple(const Tpl& tpl, std::index_sequence, L&& lambda) { if constexpr(reversed) { - iterate_tuple(tpl, reverse_index_sequence(std::index_sequence{}), std::forward(lambda)); + iterate_tuple(tpl, mpl::reverse_index_sequence(std::index_sequence{}), std::forward(lambda)); } else { - (lambda(std::get(tpl)), ...); + (lambda(std::get(tpl)), ...); } } #else template void iterate_tuple(const Tpl& /*tpl*/, std::index_sequence<>, L&& /*lambda*/) {} - template - void iterate_tuple(const Tpl& tpl, std::index_sequence, L&& lambda) { + template + void iterate_tuple(const Tpl& tpl, std::index_sequence, L&& lambda) { #ifdef SQLITE_ORM_IF_CONSTEXPR_SUPPORTED if constexpr(reversed) { #else if(reversed) { #endif - iterate_tuple(tpl, std::index_sequence{}, std::forward(lambda)); + iterate_tuple(tpl, std::index_sequence{}, std::forward(lambda)); lambda(std::get(tpl)); } else { - lambda(std::get(tpl)); - iterate_tuple(tpl, std::index_sequence{}, std::forward(lambda)); + int poormansfold[] = {(lambda(std::get(tpl)), int{}), (lambda(std::get(tpl)), int{})...}; + (void)poormansfold; } } #endif @@ -9994,28 +11046,34 @@ namespace sqlite_orm { } #ifdef SQLITE_ORM_FOLD_EXPRESSIONS_SUPPORTED - template - void iterate_tuple(std::index_sequence, L&& lambda) { - (lambda((std::tuple_element_t*)nullptr), ...); + template + void iterate_tuple(const mpl::uple& tpl, L&& lambda) { + (lambda(std::get(tpl)), ...); } #else - template - void iterate_tuple(std::index_sequence<>, L&& /*lambda*/) {} - - template - void iterate_tuple(std::index_sequence, L&& lambda) { - lambda((std::tuple_element_t*)nullptr); - iterate_tuple(std::index_sequence{}, std::forward(lambda)); + template + void iterate_tuple(const mpl::uple& tpl, L&& lambda) { + int poormansfold[] = {int{}, (lambda(std::get(tpl)), int{})...}; + (void)poormansfold; } #endif - template - void iterate_tuple(L&& lambda) { - iterate_tuple(std::make_index_sequence::value>{}, std::forward(lambda)); + +#ifdef SQLITE_ORM_FOLD_EXPRESSIONS_SUPPORTED + template + void iterate_pack(mpl::pack, L&& lambda) { + (lambda((X*)nullptr), ...); + } +#else + template + void iterate_pack(mpl::pack, L&& lambda) { + int poormansfold[] = {int{}, (lambda((X*)nullptr), int{})...}; + (void)poormansfold; } +#endif - template - R create_from_tuple(Tpl&& tpl, std::index_sequence, Projection project = {}) { - return R{polyfill::invoke(project, std::get(std::forward(tpl)))...}; + template + R create_from_tuple(Tpl&& tpl, std::index_sequence, Projection project = {}) { + return R{polyfill::invoke(project, std::get(std::forward(tpl)))...}; } template @@ -10083,7 +11141,7 @@ namespace sqlite_orm { template struct table_t : basic_table { using object_type = T; - using elements_type = std::tuple; + using elements_type = mpl::tuple; static constexpr bool is_without_rowid_v = WithoutRowId; using is_without_rowid = polyfill::bool_constant; @@ -10091,7 +11149,8 @@ namespace sqlite_orm { elements_type elements; #ifndef SQLITE_ORM_AGGREGATE_BASES_SUPPORTED - table_t(std::string name_, elements_type elements_) : basic_table{move(name_)}, elements{move(elements_)} {} + table_t(std::string name_, elements_type elements_) : + basic_table{move(name_)}, elements{std::move(elements_)} {} #endif table_t without_rowid() const { @@ -10149,8 +11208,9 @@ namespace sqlite_orm { using generated_op_index_sequence = filter_tuple_sequence_t, is_generated_always>; - constexpr size_t opIndex = first_index_sequence_value(generated_op_index_sequence{}); - result = &get(column.constraints).storage; + constexpr size_t opIndex = + mpl::first_index_sequence_value(generated_op_index_sequence{}); + result = &std::get(column.constraints).storage; }); #endif return result; @@ -10331,10 +11391,10 @@ namespace sqlite_orm { * * The mapped object type is determined implicitly from the first column definition. */ - template>::object_type> + template::object_type> internal::table_t make_table(std::string name, Cs... args) { SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES( - return {move(name), std::make_tuple(std::forward(args)...)}); + return {move(name), mpl::make_tuple(std::forward(args)...)}); } /** @@ -10345,7 +11405,7 @@ namespace sqlite_orm { template internal::table_t make_table(std::string name, Cs... args) { SQLITE_ORM_CLANG_SUPPRESS_MISSING_BRACES( - return {move(name), std::make_tuple(std::forward(args)...)}); + return {move(name), mpl::make_tuple(std::forward(args)...)}); } } #pragma once @@ -10396,7 +11456,7 @@ namespace sqlite_orm { std::string find_table_name(const DBOs& dbObjects, const std::type_index& ti) { std::string res; iterate_tuple(dbObjects, tables_index_sequence{}, [&ti, &res](const auto& table) { - using table_type = std::decay_t; + using table_type = std::remove_reference_t; if(ti == typeid(object_type_t)) { res = table.name; } @@ -10482,7 +11542,6 @@ namespace sqlite_orm { #include // std::stringstream #include // std::map #include // std::vector -#include // std::tuple_size, std::tuple, std::make_tuple, std::tie #include // std::forward, std::pair #include // std::for_each, std::ranges::for_each // #include "functional/cxx_optional.h" @@ -10648,7 +11707,6 @@ namespace sqlite_orm { #include #include // std::string #include // std::forward, std::move -#include // std::tuple, std::make_tuple // #include "row_extractor.h" @@ -10782,7 +11840,7 @@ namespace sqlite_orm { #include // std::unique_ptr #include // std::iterator_traits #include // std::string -#include // std::integral_constant, std::declval +#include // std::integral_constant, std::declval, std::decay #include // std::pair // #include "functional/cxx_universal.h" @@ -10791,6 +11849,10 @@ namespace sqlite_orm { // #include "functional/cxx_functional_polyfill.h" +// #include "functional/pack.h" + +// #include "functional/tuple.h" + // #include "tuple_helper/tuple_filter.h" // #include "connection_holder.h" @@ -10874,20 +11936,21 @@ namespace sqlite_orm { // #include "values.h" #include // std::vector -#include // std::tuple #include // std::forward // #include "functional/cxx_universal.h" // #include "functional/cxx_type_traits_polyfill.h" +// #include "functional/tuple.h" + namespace sqlite_orm { namespace internal { template struct values_t { - using args_tuple = std::tuple; + using args_tuple = mpl::tuple; args_tuple tuple; }; @@ -10919,12 +11982,12 @@ namespace sqlite_orm { // #include "ast/upsert_clause.h" -#include // std::tuple, std::make_tuple -#include // std::false_type, std::true_type #include // std::forward, std::move // #include "../functional/cxx_type_traits_polyfill.h" +// #include "../functional/tuple.h" + namespace sqlite_orm { namespace internal { #if SQLITE_VERSION_NUMBER >= 3024000 @@ -10933,24 +11996,24 @@ namespace sqlite_orm { template struct conflict_target { - using args_tuple = std::tuple; + using args_tuple = mpl::tuple; args_tuple args; - upsert_clause> do_nothing() { - return {move(this->args), {}}; + upsert_clause> do_nothing() { + return {std::move(this->args), {}}; } template - upsert_clause> do_update(ActionsArgs... actions) { - return {move(this->args), {std::make_tuple(std::forward(actions)...)}}; + upsert_clause> do_update(ActionsArgs... actions) { + return {std::move(this->args), {std::forward(actions)...}}; } }; template - struct upsert_clause, std::tuple> { - using target_args_tuple = std::tuple; - using actions_tuple = std::tuple; + struct upsert_clause, mpl::tuple> { + using target_args_tuple = mpl::tuple; + using actions_tuple = mpl::tuple; target_args_tuple target_args; @@ -10975,7 +12038,7 @@ namespace sqlite_orm { */ template internal::conflict_target on_conflict(Args... args) { - return {std::tuple(std::forward(args)...)}; + return {{std::forward(args)...}}; } #endif } @@ -11065,7 +12128,7 @@ namespace sqlite_orm { using type = T; using return_type = R; - using conditions_type = std::tuple; + using conditions_type = mpl::tuple; conditions_type conditions; }; @@ -11075,7 +12138,7 @@ namespace sqlite_orm { using type = T; using return_type = R; - using conditions_type = std::tuple; + using conditions_type = mpl::tuple; conditions_type conditions; }; @@ -11086,7 +12149,7 @@ namespace sqlite_orm { using type = T; using return_type = R; - using conditions_type = std::tuple; + using conditions_type = mpl::tuple; conditions_type conditions; }; @@ -11098,7 +12161,7 @@ namespace sqlite_orm { template struct update_all_t, Wargs...> { using set_type = set_t; - using conditions_type = std::tuple; + using conditions_type = mpl::tuple; set_type set; conditions_type conditions; @@ -11107,7 +12170,7 @@ namespace sqlite_orm { template struct remove_all_t { using type = T; - using conditions_type = std::tuple; + using conditions_type = mpl::tuple; conditions_type conditions; }; @@ -11115,7 +12178,7 @@ namespace sqlite_orm { template struct get_t { using type = T; - using ids_type = std::tuple; + using ids_type = mpl::tuple; ids_type ids; }; @@ -11123,7 +12186,7 @@ namespace sqlite_orm { template struct get_pointer_t { using type = T; - using ids_type = std::tuple; + using ids_type = mpl::tuple; ids_type ids; }; @@ -11132,7 +12195,7 @@ namespace sqlite_orm { template struct get_optional_t { using type = T; - using ids_type = std::tuple; + using ids_type = mpl::tuple; ids_type ids; }; @@ -11148,7 +12211,7 @@ namespace sqlite_orm { template struct remove_t { using type = T; - using ids_type = std::tuple; + using ids_type = mpl::tuple; ids_type ids; }; @@ -11222,7 +12285,7 @@ namespace sqlite_orm { template struct insert_raw_t { - using args_tuple = std::tuple; + using args_tuple = mpl::tuple; args_tuple args; }; @@ -11235,7 +12298,7 @@ namespace sqlite_orm { template struct replace_raw_t { - using args_tuple = std::tuple; + using args_tuple = mpl::tuple; args_tuple args; }; @@ -11342,7 +12405,7 @@ namespace sqlite_orm { */ template internal::insert_raw_t insert(Args... args) { - using args_tuple = std::tuple; + using args_tuple = mpl::pack; using internal::count_tuple; using internal::is_columns; using internal::is_insert_constraint; @@ -11414,7 +12477,7 @@ namespace sqlite_orm { */ template internal::replace_raw_t replace(Args... args) { - using args_tuple = std::tuple; + using args_tuple = mpl::tuple; using internal::count_tuple; using internal::is_columns; using internal::is_into; @@ -11556,8 +12619,8 @@ namespace sqlite_orm { */ template internal::remove_t remove(Ids... ids) { - std::tuple idsTuple{std::forward(ids)...}; - return {move(idsTuple)}; + mpl::tuple idsTuple{std::forward(ids)...}; + return {std::move(idsTuple)}; } /** @@ -11579,8 +12642,7 @@ namespace sqlite_orm { */ template internal::get_t get(Ids... ids) { - std::tuple idsTuple{std::forward(ids)...}; - return {move(idsTuple)}; + return {mpl::make_tuple(std::forward(ids)...)}; } /** @@ -11590,8 +12652,7 @@ namespace sqlite_orm { */ template internal::get_pointer_t get_pointer(Ids... ids) { - std::tuple idsTuple{std::forward(ids)...}; - return {move(idsTuple)}; + return {mpl::make_tuple(std::forward(ids)...)}; } #ifdef SQLITE_ORM_OPTIONAL_SUPPORTED @@ -11602,8 +12663,7 @@ namespace sqlite_orm { */ template internal::get_optional_t get_optional(Ids... ids) { - std::tuple idsTuple{std::forward(ids)...}; - return {move(idsTuple)}; + return {mpl::make_tuple(std::forward(ids)...)}; } #endif // SQLITE_ORM_OPTIONAL_SUPPORTED @@ -11614,10 +12674,10 @@ namespace sqlite_orm { */ template internal::remove_all_t remove_all(Args... args) { - using args_tuple = std::tuple; + using args_tuple = mpl::tuple; internal::validate_conditions(); args_tuple conditions{std::forward(args)...}; - return {move(conditions)}; + return {std::move(conditions)}; } /** @@ -11627,10 +12687,10 @@ namespace sqlite_orm { */ template internal::get_all_t, Args...> get_all(Args... args) { - using args_tuple = std::tuple; + using args_tuple = mpl::tuple; internal::validate_conditions(); args_tuple conditions{std::forward(args)...}; - return {move(conditions)}; + return {std::move(conditions)}; } /** @@ -11641,10 +12701,10 @@ namespace sqlite_orm { */ template internal::get_all_t get_all(Args... args) { - using args_tuple = std::tuple; + using args_tuple = mpl::tuple; internal::validate_conditions(); args_tuple conditions{std::forward(args)...}; - return {move(conditions)}; + return {std::move(conditions)}; } /** @@ -11653,10 +12713,10 @@ namespace sqlite_orm { */ template internal::update_all_t, Wargs...> update_all(internal::set_t set, Wargs... wh) { - using args_tuple = std::tuple; + using args_tuple = mpl::tuple; internal::validate_conditions(); args_tuple conditions{std::forward(wh)...}; - return {std::move(set), move(conditions)}; + return {std::move(set), std::move(conditions)}; } /** @@ -11666,10 +12726,10 @@ namespace sqlite_orm { */ template internal::get_all_pointer_t>, Args...> get_all_pointer(Args... args) { - using args_tuple = std::tuple; + using args_tuple = mpl::tuple; internal::validate_conditions(); args_tuple conditions{std::forward(args)...}; - return {move(conditions)}; + return {std::move(conditions)}; } /** * Create a get all pointer statement. @@ -11679,10 +12739,10 @@ namespace sqlite_orm { */ template internal::get_all_pointer_t get_all_pointer(Args... args) { - using args_tuple = std::tuple; + using args_tuple = mpl::tuple; internal::validate_conditions(); args_tuple conditions{std::forward(args)...}; - return {move(conditions)}; + return {std::move(conditions)}; } #ifdef SQLITE_ORM_OPTIONAL_SUPPORTED @@ -11693,10 +12753,10 @@ namespace sqlite_orm { */ template internal::get_all_optional_t>, Args...> get_all_optional(Args... args) { - using args_tuple = std::tuple; + using args_tuple = mpl::tuple; internal::validate_conditions(); args_tuple conditions{std::forward(args)...}; - return {move(conditions)}; + return {std::move(conditions)}; } /** @@ -11707,10 +12767,10 @@ namespace sqlite_orm { */ template internal::get_all_optional_t get_all_optional(Args... args) { - using args_tuple = std::tuple; + using args_tuple = mpl::tuple; internal::validate_conditions(); args_tuple conditions{std::forward(args)...}; - return {move(conditions)}; + return {std::move(conditions)}; } #endif // SQLITE_ORM_OPTIONAL_SUPPORTED } @@ -11860,8 +12920,8 @@ namespace sqlite_orm { }; template - struct ast_iterator, std::tuple>, void> { - using node_type = upsert_clause, std::tuple>; + struct ast_iterator, mpl::tuple>, void> { + using node_type = upsert_clause, mpl::tuple>; template void operator()(const node_type& expression, L& lambda) const { @@ -12082,6 +13142,18 @@ namespace sqlite_orm { } }; + template + struct ast_iterator, void> { + using node_type = mpl::tuple; + + template + void operator()(const node_type& node, L& lambda) const { + iterate_tuple(node, [&lambda](auto& v) { + iterate_ast(v, lambda); + }); + } + }; + template struct ast_iterator, void> { using node_type = group_by_with_having; @@ -12485,7 +13557,7 @@ namespace sqlite_orm { get_all_t, Args...> args; view_t(storage_type& stor, decltype(connection) conn, Args&&... args_) : - storage(stor), connection(std::move(conn)), args{std::make_tuple(std::forward(args_)...)} {} + storage(stor), connection(std::move(conn)), args{mpl::make_tuple(std::forward(args_)...)} {} size_t size() { return this->storage.template count(); @@ -12556,7 +13628,7 @@ namespace sqlite_orm { // #include "serializing_util.h" -#include // std::index_sequence +#include // std::index_sequence, std::remove_reference #include #include #include @@ -12571,6 +13643,10 @@ namespace sqlite_orm { // #include "functional/cxx_type_traits_polyfill.h" +// #include "functional/tuple.h" + +// #include "functional/type_at.h" + // #include "tuple_helper/tuple_iteration.h" // #include "error_code.h" @@ -12685,7 +13761,7 @@ namespace sqlite_orm { struct streaming { template auto operator()(const Ts&... ts) const { - return std::forward_as_tuple(*this, ts...); + return mpl::forward_as_tuple(*this, ts...); } template @@ -12711,9 +13787,9 @@ namespace sqlite_orm { // space + space-separated template std::ostream& operator<<(std::ostream& ss, - std::tuple&, T, Ctx> tpl) { - const auto& conditions = get<1>(tpl); - auto& context = get<2>(tpl); + mpl::tuple&, T, Ctx> tpl) { + const auto& conditions = std::get<1>(tpl); + auto& context = std::get<2>(tpl); iterate_tuple(conditions, [&ss, &context](auto& c) { ss << " " << serialize(c, context); @@ -12724,9 +13800,9 @@ namespace sqlite_orm { // serialize and stream a tuple of action expressions; // space-separated template - std::ostream& operator<<(std::ostream& ss, std::tuple&, T, Ctx> tpl) { - const auto& actions = get<1>(tpl); - auto& context = get<2>(tpl); + std::ostream& operator<<(std::ostream& ss, mpl::tuple&, T, Ctx> tpl) { + const auto& actions = std::get<1>(tpl); + auto& context = std::get<2>(tpl); iterate_tuple(actions, [&ss, &context, first = true](auto& action) mutable { constexpr std::array sep = {" ", ""}; @@ -12739,9 +13815,9 @@ namespace sqlite_orm { // comma-separated template std::ostream& operator<<(std::ostream& ss, - std::tuple&, T, Ctx> tpl) { - const auto& args = get<1>(tpl); - auto& context = get<2>(tpl); + mpl::tuple&, T, Ctx> tpl) { + const auto& args = std::get<1>(tpl); + auto& context = std::get<2>(tpl); iterate_tuple(args, [&ss, &context, first = true](auto& arg) mutable { constexpr std::array sep = {", ", ""}; @@ -12755,9 +13831,9 @@ namespace sqlite_orm { template std::ostream& operator<<( std::ostream& ss, - std::tuple&, const std::tuple...>&, Ctx> tpl) { - const auto& args = get<1>(tpl); - auto& context = get<2>(tpl); + mpl::tuple&, const mpl::tuple...>&, Ctx> tpl) { + const auto& args = std::get<1>(tpl); + auto& context = std::get<2>(tpl); iterate_tuple(args, [&ss, &context, first = true](auto& arg) mutable { constexpr std::array sep = {", ", ""}; @@ -12770,9 +13846,9 @@ namespace sqlite_orm { // comma-separated template std::ostream& operator<<(std::ostream& ss, - std::tuple&, C, Ctx> tpl) { - const auto& args = get<1>(tpl); - auto& context = get<2>(tpl); + mpl::tuple&, C, Ctx> tpl) { + const auto& args = std::get<1>(tpl); + auto& context = std::get<2>(tpl); constexpr std::array sep = {", ", ""}; for(size_t i = 0, first = true; i < args.size(); ++i) { @@ -12784,8 +13860,8 @@ namespace sqlite_orm { // stream a vector of already serialized strings; // comma-separated template - std::ostream& operator<<(std::ostream& ss, std::tuple&, C> tpl) { - const auto& strings = get<1>(tpl); + std::ostream& operator<<(std::ostream& ss, mpl::tuple&, C> tpl) { + const auto& strings = std::get<1>(tpl); constexpr std::array sep = {", ", ""}; for(size_t i = 0, first = true; i < strings.size(); ++i) { @@ -12800,7 +13876,7 @@ namespace sqlite_orm { // 3. qualifier, identifier, alias template std::ostream& operator<<(std::ostream& ss, - std::tuple&, Strings...> tpl) { + mpl::tuple&, Strings...> tpl) { stream_identifier(ss, tpl, streaming_identifier.offset_index(std::index_sequence_for{})); return ss; } @@ -12813,8 +13889,8 @@ namespace sqlite_orm { // // comma-separated template - std::ostream& operator<<(std::ostream& ss, std::tuple&, C> tpl) { - const auto& identifiers = get<1>(tpl); + std::ostream& operator<<(std::ostream& ss, mpl::tuple&, C> tpl) { + const auto& identifiers = std::get<1>(tpl); constexpr std::array sep = {", ", ""}; bool first = true; @@ -12828,9 +13904,9 @@ namespace sqlite_orm { // stream placeholders as part of a values clause template std::ostream& operator<<(std::ostream& ss, - std::tuple&, Ts...> tpl) { - const size_t& columnsCount = get<1>(tpl); - const ptrdiff_t& valuesCount = get<2>(tpl); + mpl::tuple&, Ts...> tpl) { + const size_t& columnsCount = std::get<1>(tpl); + const ptrdiff_t& valuesCount = std::get<2>(tpl); if(!valuesCount || !columnsCount) { return ss; @@ -12857,9 +13933,9 @@ namespace sqlite_orm { // comma-separated template std::ostream& operator<<(std::ostream& ss, - std::tuple&, Table, const bool&> tpl) { - const auto& table = get<1>(tpl); - const bool& qualified = get<2>(tpl); + mpl::tuple&, Table, const bool&> tpl) { + const auto& table = std::get<1>(tpl); + const bool& qualified = std::get<2>(tpl); table.for_each_column([&ss, &tableName = qualified ? table.name : std::string{}, first = true]( const column_identifier& column) mutable { @@ -12874,8 +13950,8 @@ namespace sqlite_orm { // comma-separated template std::ostream& operator<<(std::ostream& ss, - std::tuple&, Table> tpl) { - const auto& table = get<1>(tpl); + mpl::tuple&, Table> tpl) { + const auto& table = std::get<1>(tpl); table.template for_each_column_excluding( [&ss, first = true](const column_identifier& column) mutable { @@ -12891,11 +13967,11 @@ namespace sqlite_orm { template std::ostream& operator<<(std::ostream& ss, - std::tuple&, PredFnCls, L, Ctx, Obj> tpl) { - using check_if_excluded = polyfill::remove_cvref_t>; - auto& excluded = get<2>(tpl); - auto& context = get<3>(tpl); - auto& object = get<4>(tpl); + mpl::tuple&, PredFnCls, L, Ctx, Obj> tpl) { + using check_if_excluded = polyfill::remove_cvref_t>; + auto& excluded = std::get<2>(tpl); + auto& context = std::get<3>(tpl); + auto& object = std::get<4>(tpl); using object_type = polyfill::remove_cvref_t; auto& table = pick_table(context.db_objects); @@ -12916,9 +13992,9 @@ namespace sqlite_orm { // comma-separated template std::ostream& operator<<(std::ostream& ss, - std::tuple&, T, Ctx> tpl) { - const auto& columns = get<1>(tpl); - auto& context = get<2>(tpl); + mpl::tuple&, T, Ctx> tpl) { + const auto& columns = std::get<1>(tpl); + auto& context = std::get<2>(tpl); iterate_tuple(columns, [&ss, &context, first = true](auto& colRef) mutable { const std::string* columnName = find_column_name(context.db_objects, colRef); @@ -12935,13 +14011,13 @@ namespace sqlite_orm { template std::ostream& operator<<(std::ostream& ss, - std::tuple&, + mpl::tuple&, const column_constraints&, const bool&, Ctx> tpl) { - const auto& column = get<1>(tpl); - const bool& isNotNull = get<2>(tpl); - auto& context = get<3>(tpl); + const auto& column = std::get<1>(tpl); + const bool& isNotNull = std::get<2>(tpl); + auto& context = std::get<3>(tpl); using constraints_type = constraints_type_t>; constexpr size_t constraintsCount = std::tuple_size::value; @@ -12954,7 +14030,7 @@ namespace sqlite_orm { iterate_tuple(column.constraints, [&constraintsStrings, &primaryKeyIndex, &autoincrementIndex, &tupleIndex, &context]( auto& constraint) { - using constraint_type = std::decay_t; + using constraint_type = polyfill::remove_cvref_t; constraintsStrings.push_back(serialize(constraint, context)); if(is_primary_key_v) { primaryKeyIndex = tupleIndex; @@ -13492,10 +14568,11 @@ namespace sqlite_orm { #include #include // std::index_sequence, std::make_index_sequence -#include // std::tuple, std::tuple_size, std::get // #include "functional/cxx_universal.h" +// #include "functional/tuple.h" + // #include "row_extractor.h" // #include "arg_values.h" @@ -13654,7 +14731,7 @@ namespace sqlite_orm { (*this)(values, tuple, std::make_index_sequence::value>{}); } - void operator()(sqlite3_value** values, std::tuple& tuple, int argsCount) const { + void operator()(sqlite3_value** values, mpl::tuple& tuple, int argsCount) const { std::get<0>(tuple) = arg_values(argsCount, values); } @@ -13899,7 +14976,7 @@ namespace sqlite_orm { auto name = ss.str(); using args_tuple = typename callable_arguments::args_tuple; using return_type = typename callable_arguments::return_type; - constexpr auto argsCount = std::is_same>::value + constexpr auto argsCount = std::is_same>::value ? -1 : int(std::tuple_size::value); this->scalarFunctions.emplace_back(new user_defined_scalar_function_t{ @@ -13961,7 +15038,7 @@ namespace sqlite_orm { auto name = ss.str(); using args_tuple = typename callable_arguments::args_tuple; using return_type = typename callable_arguments::return_type; - constexpr auto argsCount = std::is_same>::value + constexpr auto argsCount = std::is_same>::value ? -1 : int(std::tuple_size::value); this->aggregateFunctions.emplace_back(new user_defined_aggregate_function_t{ @@ -13977,7 +15054,7 @@ namespace sqlite_orm { args_tuple argsTuple; using tuple_size = std::tuple_size; values_to_tuple{}(values, argsTuple, argsCount); - call(function, &F::step, move(argsTuple)); + call(function, &F::step, std::move(argsTuple)); }, /* finalCall = */ [](sqlite3_context* context, void* functionVoidPointer) { @@ -14611,6 +15688,10 @@ namespace sqlite_orm { // #include "functional/mpl.h" +// #include "functional/pack.h" + +// #include "functional/type_at.h" + // #include "tuple_helper/tuple_filter.h" // #include "ast/upsert_clause.h" @@ -15124,16 +16205,16 @@ namespace sqlite_orm { } }; - template - struct statement_serializer, std::tuple>, void> { - using statement_type = upsert_clause, std::tuple>; + template + struct statement_serializer> { + using statement_type = T; template std::string operator()(const statement_type& statement, const Ctx& context) const { std::stringstream ss; ss << "ON CONFLICT"; iterate_tuple(statement.target_args, [&ss, &context](auto& value) { - using value_type = std::decay_t; + using value_type = std::remove_reference_t; auto needParenthesis = std::is_member_pointer::value; ss << ' '; if(needParenthesis) { @@ -15612,9 +16693,7 @@ namespace sqlite_orm { ss << "NOT IN"; } ss << " "; - using args_type = std::tuple; - constexpr bool theOnlySelect = - std::tuple_size::value == 1 && is_select_v>; + constexpr bool theOnlySelect = sizeof...(Args) == 1 && is_select_v>; if(!theOnlySelect) { ss << "("; } @@ -15750,17 +16829,17 @@ namespace sqlite_orm { } }; - template - struct statement_serializer, std::tuple>, void> { - using statement_type = foreign_key_t, std::tuple>; + template + struct statement_serializer> { + using statement_type = FK; template std::string operator()(const statement_type& fk, const Ctx& context) const { std::stringstream ss; ss << "FOREIGN KEY(" << streaming_mapped_columns_expressions(fk.columns, context) << ") REFERENCES "; { - using references_type_t = typename std::decay_t::references_type; - using first_reference_t = std::tuple_element_t<0, references_type_t>; + using references_type_t = typename std::remove_reference_t::references_type; + using first_reference_t = mpl::element_at_t<0, references_type_t>; using first_reference_mapped_type = table_type_of_t; auto refTableName = lookup_table_name(context.db_objects); ss << streaming_identifier(refTableName); @@ -15855,8 +16934,7 @@ namespace sqlite_orm { template std::string operator()(const statement_type& statement, const Ctx& context) const { - using expression_type = std::decay_t; - using object_type = typename expression_object_type::type; + using object_type = typename expression_object_type::type; auto& table = pick_table(context.db_objects); std::stringstream ss; ss << "REPLACE INTO " << streaming_identifier(table.name) << " (" @@ -15877,10 +16955,9 @@ namespace sqlite_orm { template std::string operator()(const statement_type& ins, const Ctx& context) const { - constexpr size_t colsCount = std::tuple_size>::value; + constexpr size_t colsCount = sizeof...(Cols); static_assert(colsCount > 0, "Use insert or replace with 1 argument instead"); - using expression_type = std::decay_t; - using object_type = typename expression_object_type::type; + using object_type = typename expression_object_type::type; auto& table = pick_table(context.db_objects); std::stringstream ss; ss << "INSERT INTO " << streaming_identifier(table.name) << " "; @@ -15888,7 +16965,7 @@ namespace sqlite_orm { << "VALUES ("; iterate_tuple(ins.columns.columns, [&ss, &context, &object = get_ref(ins.obj), first = true](auto& memberPointer) mutable { - using member_pointer_type = std::decay_t; + using member_pointer_type = polyfill::remove_cvref_t; static_assert(!is_setter_v, "Unable to use setter within insert explicit"); @@ -15907,8 +16984,7 @@ namespace sqlite_orm { template std::string operator()(const statement_type& statement, const Ctx& context) const { - using expression_type = std::decay_t; - using object_type = typename expression_object_type::type; + using object_type = typename expression_object_type::type; auto& table = pick_table(context.db_objects); std::stringstream ss; @@ -16000,7 +17076,7 @@ namespace sqlite_orm { std::string operator()(const statement_type& statement, const Ctx& context) const { using object_type = typename expression_object_type::type; auto& table = pick_table(context.db_objects); - using is_without_rowid = typename std::decay_t::is_without_rowid; + using is_without_rowid = typename std::remove_reference_t::is_without_rowid; std::vector> columnNames; table.template for_each_column_excluding< @@ -16085,7 +17161,7 @@ namespace sqlite_orm { ss << "REPLACE"; } iterate_tuple(statement.args, [&context, &ss](auto& value) { - using value_type = std::decay_t; + using value_type = polyfill::remove_cvref_t; ss << ' '; if(is_columns_v) { auto newContext = context; @@ -16139,8 +17215,7 @@ namespace sqlite_orm { template std::string operator()(const statement_type& rep, const Ctx& context) const { - using expression_type = std::decay_t; - using object_type = typename expression_object_type::type; + using object_type = typename expression_object_type::type; auto& table = pick_table(context.db_objects); std::stringstream ss; @@ -16161,7 +17236,7 @@ namespace sqlite_orm { std::string operator()(const statement_type& statement, const Ctx& context) const { using object_type = typename expression_object_type::type; auto& table = pick_table(context.db_objects); - using is_without_rowid = typename std::decay_t::is_without_rowid; + using is_without_rowid = typename std::remove_reference_t::is_without_rowid; std::vector> columnNames; table.template for_each_column_excluding< @@ -16350,12 +17425,12 @@ namespace sqlite_orm { table_name_collector collector([&context](const std::type_index& ti) { return find_table_name(context.db_objects, ti); }); - constexpr bool explicitFromItemsCount = count_tuple, is_from>::value; + constexpr bool explicitFromItemsCount = count_tuple, is_from>::value; if(!explicitFromItemsCount) { iterate_ast(sel.col, collector); iterate_ast(sel.conditions, collector); join_iterator()([&collector, &context](const auto& c) { - using original_join_type = typename std::decay_t::join_type::type; + using original_join_type = typename std::remove_reference_t::join_type::type; using cross_join_type = mapped_type_proxy_t; auto crossJoinedTableName = lookup_table_name(context.db_objects); auto tableAliasString = alias_extractor::get(); @@ -16415,15 +17490,15 @@ namespace sqlite_orm { if(statement.unique) { ss << "UNIQUE "; } - using elements_type = typename std::decay_t::elements_type; - using head_t = typename std::tuple_element_t<0, elements_type>::column_type; + using elements_type = typename std::remove_reference_t::elements_type; + using head_t = typename mpl::element_at_t<0, elements_type>::column_type; using indexed_type = table_type_of_t; ss << "INDEX IF NOT EXISTS " << streaming_identifier(statement.name) << " ON " << streaming_identifier(lookup_table_name(context.db_objects)); std::vector columnNames; std::string whereString; iterate_tuple(statement.elements, [&columnNames, &context, &whereString](auto& value) { - using value_type = std::decay_t; + using value_type = polyfill::remove_cvref_t; if(!is_where_v) { auto newContext = context; newContext.use_parentheses = false; @@ -16442,17 +17517,15 @@ namespace sqlite_orm { } }; - template - struct statement_serializer, void> { - using statement_type = from_t; + template + struct statement_serializer> { + using statement_type = T; template std::string operator()(const statement_type&, const Ctx& context) const { - using tuple = std::tuple; - std::stringstream ss; ss << "FROM "; - iterate_tuple([&context, &ss, first = true](auto* item) mutable { + iterate_pack(typename statement_type::pack_type{}, [&context, &ss, first = true](auto* item) mutable { using from_type = std::remove_pointer_t; constexpr std::array sep = {", ", ""}; @@ -16613,7 +17686,7 @@ namespace sqlite_orm { << serialize(statement.base, context); ss << " BEGIN "; iterate_tuple(statement.elements, [&ss, &context](auto& element) { - using element_type = std::decay_t; + using element_type = polyfill::remove_cvref_t; if(is_select_v) { auto newContext = context; newContext.use_parentheses = false; @@ -16989,7 +18062,7 @@ namespace sqlite_orm { template void create_table(sqlite3* db, const std::string& tableName, const Table& table) { - using table_type = std::decay_t; + using table_type = std::remove_reference_t; using context_t = serializer_context; std::stringstream ss; @@ -17060,8 +18133,8 @@ namespace sqlite_orm { template void assert_mapped_type() const { - using mapped_types_tuple = std::tuple; - static_assert(mpl::invoke_t, mapped_types_tuple>::value, + using mapped_types_pack = mpl::pack; + static_assert(mpl::invoke_t, mapped_types_pack>::value, "type is not mapped to a storage"); } @@ -17345,11 +18418,7 @@ namespace sqlite_orm { * @param m is a class member pointer (the same you passed into make_column). * @return group_concat query result. */ - template, - std::enable_if_t::value >= 1, bool> = true> + template= 1, bool> = true> std::string group_concat(F O::*m, Args&&... args) { return this->group_concat_internal(m, {}, std::forward(args)...); } @@ -17454,8 +18523,7 @@ namespace sqlite_orm { */ template> std::vector select(T m, Args... args) { - static_assert(!is_base_of_template_v || - std::tuple_size>::value == 0, + static_assert(!is_base_of_template_v || sizeof...(Args) == 0, "Cannot use args with a compound operator"); auto statement = this->prepare(sqlite_orm::select(std::move(m), std::forward(args)...)); return this->execute(statement); @@ -17498,7 +18566,7 @@ namespace sqlite_orm { std::stringstream ss; ss << "{ "; table.for_each_column([&ss, &object, first = true](auto& column) mutable { - using column_type = std::decay_t; + using column_type = std::remove_reference_t; using field_type = typename column_type::field_type; constexpr std::array sep = {", ", ""}; @@ -18021,7 +19089,7 @@ namespace sqlite_orm { template int64 execute(const prepared_statement_t>& statement) { - using statement_type = std::decay_t; + using statement_type = std::remove_reference_t; using expression_type = typename statement_type::expression_type; using object_type = typename expression_object_type::type; @@ -18039,7 +19107,7 @@ namespace sqlite_orm { template, is_replace_range>, bool> = true> void execute(const prepared_statement_t& statement) { - using statement_type = std::decay_t; + using statement_type = std::remove_reference_t; using expression_type = typename statement_type::expression_type; using object_type = typename expression_object_type::type; @@ -18080,7 +19148,7 @@ namespace sqlite_orm { template, is_insert_range>, bool> = true> int64 execute(const prepared_statement_t& statement) { - using statement_type = std::decay_t; + using statement_type = std::remove_reference_t; using expression_type = typename statement_type::expression_type; using object_type = typename expression_object_type::type; @@ -18088,7 +19156,7 @@ namespace sqlite_orm { auto processObject = [&table = this->get_table(), bind_value = field_value_binder{stmt}](auto& object) mutable { - using is_without_rowid = typename std::decay_t::is_without_rowid; + using is_without_rowid = typename std::remove_reference_t::is_without_rowid; table.template for_each_column_excluding< mpl::conjunction>, mpl::disjunction_fn>>( @@ -18134,7 +19202,7 @@ namespace sqlite_orm { template void execute(const prepared_statement_t>& statement) { - using statement_type = std::decay_t; + using statement_type = std::remove_reference_t; using expression_type = typename statement_type::expression_type; using object_type = typename expression_object_type::type; @@ -18374,6 +19442,10 @@ namespace sqlite_orm { #include // std::reference_wrapper // #include "functional/cxx_optional.h" +// #include "functional/type_at.h" + +// #include "functional/tuple.h" + // #include "tuple_helper/tuple_filter.h" // #include "conditions.h" @@ -18406,7 +19478,7 @@ namespace sqlite_orm { template struct node_tuple { - using type = std::tuple; + using type = mpl::tuple; }; template @@ -18414,7 +19486,7 @@ namespace sqlite_orm { template<> struct node_tuple { - using type = std::tuple<>; + using type = mpl::tuple<>; }; #ifdef SQLITE_ORM_OPTIONAL_SUPPORTED template @@ -18424,18 +19496,18 @@ namespace sqlite_orm { struct node_tuple, void> : node_tuple {}; template - struct node_tuple, void> : node_tuple> {}; + struct node_tuple, void> : node_tuple> {}; template struct node_tuple, void> { - using args_tuple = node_tuple_t>; + using args_tuple = node_tuple_t>; using expression_tuple = node_tuple_t; using type = tuple_cat_t; }; template - struct node_tuple, std::tuple>, void> - : node_tuple> {}; + struct node_tuple, mpl::tuple>, void> + : node_tuple> {}; template struct node_tuple, void> { @@ -18542,6 +19614,11 @@ namespace sqlite_orm { using type = tuple_cat_t...>; }; + template + struct node_tuple, void> { + using type = tuple_cat_t...>; + }; + template struct node_tuple, void> { using type = tuple_cat_t...>; @@ -18698,6 +19775,10 @@ namespace sqlite_orm { // #include "functional/static_magic.h" +// #include "functional/cxx_type_traits_polyfill.h" + +// #include "functional/type_at.h" + // #include "prepared_statement.h" // #include "ast_iterator.h" @@ -18818,24 +19899,24 @@ namespace sqlite_orm { template const auto& get(const internal::prepared_statement_t& statement) { - using statement_type = std::decay_t; + using statement_type = std::remove_reference_t; using expression_type = typename statement_type::expression_type; using node_tuple = internal::node_tuple_t; using bind_tuple = internal::bindable_filter_t; - using result_type = std::tuple_element_t(N), bind_tuple>; + using result_type = mpl::element_at_t(N), bind_tuple>; const result_type* result = nullptr; internal::iterate_ast(statement.expression, [&result, index = -1](auto& node) mutable { - using node_type = std::decay_t; + using node_type = polyfill::remove_cvref_t; if(internal::is_bindable_v) { ++index; - } - if(index == N) { - internal::call_if_constexpr::value>( - [](auto& r, auto& n) { - r = &n; - }, - result, - node); + if(index == N) { + internal::call_if_constexpr::value>( + [](auto& r, auto& n) { + r = &n; + }, + result, + node); + } } }); return internal::get_ref(*result); @@ -18843,25 +19924,25 @@ namespace sqlite_orm { template auto& get(internal::prepared_statement_t& statement) { - using statement_type = std::decay_t; + using statement_type = std::remove_reference_t; using expression_type = typename statement_type::expression_type; using node_tuple = internal::node_tuple_t; using bind_tuple = internal::bindable_filter_t; - using result_type = std::tuple_element_t(N), bind_tuple>; + using result_type = mpl::element_at_t(N), bind_tuple>; result_type* result = nullptr; internal::iterate_ast(statement.expression, [&result, index = -1](auto& node) mutable { - using node_type = std::decay_t; + using node_type = polyfill::remove_cvref_t; if(internal::is_bindable_v) { ++index; - } - if(index == N) { - internal::call_if_constexpr::value>( - [](auto& r, auto& n) { - r = const_cast>(&n); - }, - result, - node); + if(index == N) { + internal::call_if_constexpr::value>( + [](auto& r, auto& n) { + r = const_cast>(&n); + }, + result, + node); + } } }); return internal::get_ref(*result); @@ -19003,7 +20084,7 @@ namespace sqlite_orm { // #include "../functional/static_magic.h" -// #include "../tuple_helper/index_sequence_util.h" +// #include "../functional/index_sequence_util.h" // #include "../tuple_helper/tuple_filter.h" @@ -19025,8 +20106,8 @@ namespace sqlite_orm { call_if_constexpr( [&value](auto& constraints, auto op_index_sequence) { using default_op_index_sequence = decltype(op_index_sequence); - constexpr size_t opIndex = first_index_sequence_value(default_op_index_sequence{}); - value = std::make_unique(serialize_default_value(get(constraints))); + constexpr size_t opIndex = mpl::first_index_sequence_value(default_op_index_sequence{}); + value = std::make_unique(serialize_default_value(std::get(constraints))); }, this->constraints, default_op_index_sequence{}); @@ -19042,7 +20123,7 @@ namespace sqlite_orm { * this file is also used to provide definitions of interface methods 'hitting the database'. */ -#include // std::decay_t +#include // std::remove_reference #include // std::move #include // std::find_if, std::ranges::find @@ -19060,7 +20141,7 @@ namespace sqlite_orm { std::vector res; res.reserve(size_t(filter_tuple_sequence_t::size())); this->for_each_column([&res](auto& column) { - using field_type = field_type_t>; + using field_type = field_type_t>; std::string dft; if(auto d = column.default_value()) { dft = move(*d); diff --git a/tests/backup_tests.cpp b/tests/backup_tests.cpp index 7db85cb8c..b8aa55d0a 100644 --- a/tests/backup_tests.cpp +++ b/tests/backup_tests.cpp @@ -26,6 +26,11 @@ namespace { }; auto initStorageMarvel(const std::string& path) { + auto table = make_table("marvel", + make_column("id", &MarvelHero::id, primary_key()), + make_column("name", &MarvelHero::name), + make_column("abilities", &MarvelHero::abilities)); + auto table2 = table; auto storage = make_storage(path, make_table("marvel", make_column("id", &MarvelHero::id, primary_key()), diff --git a/tests/constraints/foreign_key.cpp b/tests/constraints/foreign_key.cpp index 794a7f28e..b1343507a 100644 --- a/tests/constraints/foreign_key.cpp +++ b/tests/constraints/foreign_key.cpp @@ -48,10 +48,10 @@ TEST_CASE("Foreign key") { STATIC_REQUIRE(storage_foreign_keys_count::value == 0); using LocationFks = storage_fk_references::type; - STATIC_REQUIRE(std::is_same>::value); + STATIC_REQUIRE(std::is_same>::value); using VisitFks = storage_fk_references::type; - STATIC_REQUIRE(std::is_same>::value); + STATIC_REQUIRE(std::is_same>::value); } storage.sync_schema(); diff --git a/tests/functional/tuple/assign.convert_copy.cpp b/tests/functional/tuple/assign.convert_copy.cpp new file mode 100644 index 000000000..a2b4cbf7e --- /dev/null +++ b/tests/functional/tuple/assign.convert_copy.cpp @@ -0,0 +1,69 @@ +#include +#include + +using namespace sqlite_orm; + +namespace { + struct B { + int id_; + explicit B(int i = 0) : id_(i) {} + }; + + struct D : B { + explicit D(int i = 0) : B(i) {} + }; +} + +template class Tuple> +static void template_template_test_case() { + { + using T0 = Tuple; + using T1 = Tuple; + T0 t0(2.5); + T1 t1; + t1 = t0; + REQUIRE(std::get<0>(t1) == 2); + } + { + using T0 = Tuple; + using T1 = Tuple; + T0 t0(2.5, 'a'); + T1 t1; + t1 = t0; + REQUIRE(std::get<0>(t1) == 2); + REQUIRE(std::get<1>(t1) == int('a')); + } + { + using T0 = Tuple; + using T1 = Tuple; + T0 t0(2.5, 'a', D(3)); + T1 t1; + t1 = t0; + REQUIRE(std::get<0>(t1) == 2); + REQUIRE(std::get<1>(t1) == int('a')); + REQUIRE(std::get<2>(t1).id_ == 3); + } + { + D d(3); + D d2(2); + using T0 = Tuple; + using T1 = Tuple; + T0 t0(2.5, 'a', d2); + T1 t1(1.5, 'b', d); + t1 = t0; + REQUIRE(std::get<0>(t1) == 2); + REQUIRE(std::get<1>(t1) == int('a')); + REQUIRE(std::get<2>(t1).id_ == 2); + } +} + +TEST_CASE("tuple - converting copy assignment") { + { + INFO("mpl::tuple"); + template_template_test_case(); + } + { + INFO("mpl::uple"); + template_template_test_case(); + } +} diff --git a/tests/functional/tuple/assign.convert_move.cpp b/tests/functional/tuple/assign.convert_move.cpp new file mode 100644 index 000000000..ff8ab5097 --- /dev/null +++ b/tests/functional/tuple/assign.convert_move.cpp @@ -0,0 +1,79 @@ +#include +#include + +using namespace sqlite_orm; + +namespace { + struct B { + int id_; + explicit B(int i = 0) : id_(i) {} + virtual ~B() {} + }; + + struct D : B { + explicit D(int i) : B(i) {} + }; +} + +template class Tuple> +static void template_template_test_case() { + { + using T0 = Tuple; + using T1 = Tuple; + T0 t0(2.5); + T1 t1; + t1 = std::move(t0); + REQUIRE(std::get<0>(t1) == 2); + } + { + using T0 = Tuple; + using T1 = Tuple; + T0 t0(2.5, 'a'); + T1 t1; + t1 = std::move(t0); + REQUIRE(std::get<0>(t1) == 2); + REQUIRE(std::get<1>(t1) == int('a')); + } + { + using T0 = Tuple; + using T1 = Tuple; + T0 t0(2.5, 'a', D(3)); + T1 t1; + t1 = std::move(t0); + REQUIRE(std::get<0>(t1) == 2); + REQUIRE(std::get<1>(t1) == int('a')); + REQUIRE(std::get<2>(t1).id_ == 3); + } + { + D d(3); + D d2(2); + using T0 = Tuple; + using T1 = Tuple; + T0 t0(2.5, 'a', d2); + T1 t1(1.5, 'b', d); + t1 = std::move(t0); + REQUIRE(std::get<0>(t1) == 2); + REQUIRE(std::get<1>(t1) == int('a')); + REQUIRE(std::get<2>(t1).id_ == 2); + } + { + using T0 = Tuple>; + using T1 = Tuple>; + T0 t0(2.5, 'a', std::unique_ptr(new D(3))); + T1 t1; + t1 = std::move(t0); + REQUIRE(std::get<0>(t1) == 2); + REQUIRE(std::get<1>(t1) == int('a')); + REQUIRE(std::get<2>(t1)->id_ == 3); + } +} + +TEST_CASE("tuple - converting move assignment") { + { + //INFO("mpl::tuple"); + //template_template_test_case(); + } { + INFO("mpl::uple"); + template_template_test_case(); + } +} diff --git a/tests/functional/tuple/assign.copy.cpp b/tests/functional/tuple/assign.copy.cpp new file mode 100644 index 000000000..06f082906 --- /dev/null +++ b/tests/functional/tuple/assign.copy.cpp @@ -0,0 +1,49 @@ +#include +#include + +using namespace sqlite_orm; + +template class Tuple> +static void template_template_test_case() { + { + using T = Tuple<>; + T t0; + T t; + t = t0; + } + { + using T = Tuple; + T t0(2); + T t; + t = t0; + REQUIRE(std::get<0>(t) == 2); + } + { + using T = Tuple; + T t0(2, 'a'); + T t; + t = t0; + REQUIRE(std::get<0>(t) == 2); + REQUIRE(std::get<1>(t) == 'a'); + } + { + using T = Tuple; + const T t0(2, 'a', "some text"); + T t; + t = t0; + REQUIRE(std::get<0>(t) == 2); + REQUIRE(std::get<1>(t) == 'a'); + REQUIRE(std::get<2>(t) == "some text"); + } +} + +TEST_CASE("tuple - copy assignment") { + { + INFO("mpl::tuple"); + template_template_test_case(); + } + { + INFO("mpl::uple"); + template_template_test_case(); + } +} diff --git a/tests/functional/tuple/assign.move.cpp b/tests/functional/tuple/assign.move.cpp new file mode 100644 index 000000000..ea5930de5 --- /dev/null +++ b/tests/functional/tuple/assign.move.cpp @@ -0,0 +1,72 @@ +#include +#include + +using namespace sqlite_orm; + +namespace { + template + struct MoveOnly { + int data_; + MoveOnly(MoveOnly const&) = delete; + MoveOnly& operator=(MoveOnly const&) = delete; + MoveOnly(int data = 1) : data_(data) {} + MoveOnly(MoveOnly&& x) : data_(x.data_) { + x.data_ = 0; + } + + MoveOnly& operator=(MoveOnly&& x) { + data_ = x.data_; + x.data_ = 0; + return *this; + } + + int get() const { + return data_; + } + bool operator==(const MoveOnly& x) const { + return data_ == x.data_; + } + bool operator<(const MoveOnly& x) const { + return data_ < x.data_; + } + }; + + using MoveOnly1 = MoveOnly<1>; + using MoveOnly2 = MoveOnly<2>; +} + +template class Tuple> +static void template_template_test_case() { + { + using T = Tuple<>; + T t0; + T t; + t = std::move(t0); + } + { + using T = Tuple; + T t0(MoveOnly1(0)); + T t; + t = std::move(t0); + REQUIRE(std::get<0>(t) == 0); + } + { + using T = Tuple; + T t0(MoveOnly1(0), MoveOnly2(1)); + T t; + t = std::move(t0); + REQUIRE(std::get<0>(t) == 0); + REQUIRE(std::get<1>(t) == 1); + } +} + +TEST_CASE("tuple - move assignment") { + { + INFO("mpl::tuple"); + template_template_test_case(); + } + { + INFO("mpl::uple"); + template_template_test_case(); + } +} diff --git a/tests/functional/tuple/cnstr.convert_copy.cpp b/tests/functional/tuple/cnstr.convert_copy.cpp new file mode 100644 index 000000000..4335b4b07 --- /dev/null +++ b/tests/functional/tuple/cnstr.convert_copy.cpp @@ -0,0 +1,104 @@ +#include +#include + +using namespace sqlite_orm; + +namespace { + struct A { + int id_; + constexpr A(int i) : id_(i) {} + friend constexpr bool operator==(const A& x, const A& y) { + return x.id_ == y.id_; + } + }; + + struct B { + int id_; + explicit B(int i) : id_(i) {} + }; + + struct C { + int id_; + constexpr explicit C(int i) : id_(i) {} + friend constexpr bool operator==(const C& x, const C& y) { + return x.id_ == y.id_; + } + }; + + struct D : B { + explicit D(int i) : B(i) {} + }; +} + +template class Tuple> +static void template_template_test_case() { + { + using T0 = Tuple; + using T1 = Tuple; + T0 t0(2.5); + T1 t1 = t0; + REQUIRE(std::get<0>(t1) == 2); + } + { + using T0 = Tuple; + using T1 = Tuple; + constexpr T0 t0(2.5); + constexpr T1 t1 = t0; + STATIC_REQUIRE(std::get<0>(t1) == 2); + } + { + using T0 = Tuple; + using T1 = Tuple; + constexpr T0 t0(2); + constexpr T1 t1{t0}; + STATIC_REQUIRE(std::get<0>(t1) == C(2)); + } + { + using T0 = Tuple; + using T1 = Tuple; + T0 t0(2.5, 'a'); + T1 t1 = t0; + REQUIRE(std::get<0>(t1) == 2); + REQUIRE(std::get<1>(t1) == int('a')); + } + { + using T0 = Tuple; + using T1 = Tuple; + T0 t0(2.5, 'a', D(3)); + T1 t1 = t0; + REQUIRE(std::get<0>(t1) == 2); + REQUIRE(std::get<1>(t1) == int('a')); + REQUIRE(std::get<2>(t1).id_ == 3); + } + { + D d(3); + using T0 = Tuple; + using T1 = Tuple; + T0 t0(2.5, 'a', d); + T1 t1 = t0; + d.id_ = 2; + REQUIRE(std::get<0>(t1) == 2); + REQUIRE(std::get<1>(t1) == int('a')); + REQUIRE(std::get<2>(t1).id_ == 2); + } + { + using T0 = Tuple; + using T1 = Tuple; + T0 t0(2.5, 'a', 3); + T1 t1(t0); + REQUIRE(std::get<0>(t1) == 2); + REQUIRE(std::get<1>(t1) == int('a')); + REQUIRE(std::get<2>(t1).id_ == 3); + } +} + +TEST_CASE("tuple - converting copy construction") { + { + INFO("mpl::tuple"); + template_template_test_case(); + } + { + INFO("mpl::uple"); + template_template_test_case(); + } +} diff --git a/tests/functional/tuple/cnstr.convert_move.cpp b/tests/functional/tuple/cnstr.convert_move.cpp new file mode 100644 index 000000000..ea4531102 --- /dev/null +++ b/tests/functional/tuple/cnstr.convert_move.cpp @@ -0,0 +1,75 @@ +#include +#include + +using namespace sqlite_orm; + +namespace { + struct B { + int id_; + explicit B(int i) : id_(i) {} + virtual ~B() {} + }; + + struct D : B { + explicit D(int i) : B(i) {} + }; +} + +template class Tuple> +static void template_template_test_case() { + { + using T0 = Tuple; + using T1 = Tuple; + T0 t0(2.5); + T1 t1 = std::move(t0); + REQUIRE(std::get<0>(t1) == 2); + } + { + using T0 = Tuple; + using T1 = Tuple; + T0 t0(2.5, 'a'); + T1 t1 = std::move(t0); + REQUIRE(std::get<0>(t1) == 2); + REQUIRE(std::get<1>(t1) == int('a')); + } + { + using T0 = Tuple; + using T1 = Tuple; + T0 t0(2.5, 'a', D(3)); + T1 t1 = std::move(t0); + REQUIRE(std::get<0>(t1) == 2); + REQUIRE(std::get<1>(t1) == int('a')); + REQUIRE(std::get<2>(t1).id_ == 3); + } + { + D d(3); + using T0 = Tuple; + using T1 = Tuple; + T0 t0(2.5, 'a', d); + T1 t1 = std::move(t0); + d.id_ = 2; + REQUIRE(std::get<0>(t1) == 2); + REQUIRE(std::get<1>(t1) == int('a')); + REQUIRE(std::get<2>(t1).id_ == 2); + } + { + using T0 = Tuple>; + using T1 = Tuple>; + T0 t0(2.5, 'a', std::unique_ptr(new D(3))); + T1 t1 = std::move(t0); + REQUIRE(std::get<0>(t1) == 2); + REQUIRE(std::get<1>(t1) == int('a')); + REQUIRE(std::get<2>(t1)->id_ == 3); + } +} + +TEST_CASE("tuple - converting move construction") { + { + INFO("mpl::tuple"); + template_template_test_case(); + } + { + INFO("mpl::uple"); + template_template_test_case(); + } +} diff --git a/tests/functional/tuple/cnstr.copy.cpp b/tests/functional/tuple/cnstr.copy.cpp new file mode 100644 index 000000000..e0938bda6 --- /dev/null +++ b/tests/functional/tuple/cnstr.copy.cpp @@ -0,0 +1,77 @@ +#include +#include + +using namespace sqlite_orm; + +namespace { + struct Empty {}; +} + +template class Tuple> +static void template_template_test_case() { + { + using T = Tuple<>; + T t0; + T t_implicit = t0; + T t_explicit(t0); + + (void)t_explicit; + (void)t_implicit; + } + { + using T = Tuple; + T t0(2); + T t = t0; + REQUIRE(std::get<0>(t) == 2); + } + { + using T = Tuple; + T t0(2, 'a'); + T t = t0; + REQUIRE(std::get<0>(t) == 2); + REQUIRE(std::get<1>(t) == 'a'); + } + { + using T = Tuple; + const T t0(2, 'a', "some text"); + T t = t0; + REQUIRE(std::get<0>(t) == 2); + REQUIRE(std::get<1>(t) == 'a'); + REQUIRE(std::get<2>(t) == "some text"); + } + { + using T = Tuple; + constexpr T t0(2); + constexpr T t = t0; + static_assert(std::get<0>(t) == 2, ""); + } + { + using T = Tuple; + constexpr T t0; + constexpr T t = t0; + constexpr Empty e = std::get<0>(t0); + (void)e; + } + { + struct T {}; + struct U {}; + + constexpr Tuple binary{}; + constexpr Tuple copy_implicit = binary; + constexpr Tuple copy_explicit(binary); + + (void)copy_implicit; + (void)copy_explicit; + } +} + +TEST_CASE("tuple - copy construction") { + { + INFO("mpl::tuple"); + template_template_test_case(); + } + { + INFO("mpl::uple"); + template_template_test_case(); + } +} diff --git a/tests/functional/tuple/cnstr.default.cpp b/tests/functional/tuple/cnstr.default.cpp new file mode 100644 index 000000000..5770349da --- /dev/null +++ b/tests/functional/tuple/cnstr.default.cpp @@ -0,0 +1,144 @@ +#include +#include + +using namespace sqlite_orm; + +namespace { + struct DefaultOnly { + int data_; + DefaultOnly(DefaultOnly const&) = delete; + DefaultOnly& operator=(DefaultOnly const&) = delete; + + static int count; + + DefaultOnly() : data_(-1) { + ++count; + } + ~DefaultOnly() { + data_ = 0; + --count; + } + + friend bool operator==(DefaultOnly const& x, DefaultOnly const& y) { + return x.data_ == y.data_; + } + + friend bool operator<(DefaultOnly const& x, DefaultOnly const& y) { + return x.data_ < y.data_; + } + }; + + int DefaultOnly::count = 0; + + struct NoDefault { + NoDefault() = delete; + explicit NoDefault(int) {} + }; + + struct IllFormedDefault { + IllFormedDefault(int x) : value(x) {} + template + constexpr IllFormedDefault() { + static_assert(Pred, "The default constructor should not be instantiated"); + } + int value; + }; +} + +template class Tuple> +static void template_template_test_case() { + { + Tuple<> t; + (void)t; + } + { + Tuple t; + REQUIRE(std::get<0>(t) == 0); + } + { + Tuple t; + REQUIRE(std::get<0>(t) == 0); + REQUIRE(std::get<1>(t) == nullptr); + } + { + Tuple t; + REQUIRE(std::get<0>(t) == 0); + REQUIRE(std::get<1>(t) == nullptr); + REQUIRE(std::get<2>(t) == ""); + } + { + Tuple t; + REQUIRE(std::get<0>(t) == 0); + REQUIRE(std::get<1>(t) == nullptr); + REQUIRE(std::get<2>(t) == ""); + REQUIRE(std::get<3>(t) == DefaultOnly()); + } + { + // See LLVM bug #21157. + STATIC_REQUIRE(!std::is_default_constructible>()); + STATIC_REQUIRE(!std::is_default_constructible>()); + } + { + struct T {}; + struct U {}; + struct V {}; + + constexpr Tuple<> z0; + (void)z0; + constexpr Tuple z1; + (void)z1; + constexpr Tuple z2; + (void)z2; + constexpr Tuple z3; + (void)z3; + } + { + constexpr Tuple t; + REQUIRE(std::get<0>(t) == 0); + } + { + constexpr Tuple t; + REQUIRE(std::get<0>(t) == 0); + REQUIRE(std::get<1>(t) == nullptr); + } + + // Make sure we can hold non default-constructible elements, and that + // it does not trigger an error in the default constructor. + { + IllFormedDefault v(0); + Tuple t1(v); + Tuple t2{v}; + Tuple t3 = {v}; + (void)t1; + (void)t2; + (void)t3; + } + { + Tuple t1(0); + Tuple t2{0}; + Tuple t3 = {0}; + (void)t1; + (void)t2; + (void)t3; + } + { + NoDefault v(0); + Tuple t1(v); + Tuple t2{v}; + Tuple t3 = {v}; + (void)t1; + (void)t2; + (void)t3; + } +} + +TEST_CASE("tuple - default construction") { + { + INFO("mpl::tuple"); + template_template_test_case(); + } + { + INFO("mpl::uple"); + template_template_test_case(); + } +} diff --git a/tests/functional/tuple/cnstr.move.cpp b/tests/functional/tuple/cnstr.move.cpp new file mode 100644 index 000000000..ed35d3835 --- /dev/null +++ b/tests/functional/tuple/cnstr.move.cpp @@ -0,0 +1,82 @@ +#include +#include + +using namespace sqlite_orm; + +namespace { + template + struct MoveOnly { + int data_; + MoveOnly(MoveOnly const&) = delete; + MoveOnly& operator=(MoveOnly const&) = delete; + MoveOnly(int data = 1) : data_(data) {} + MoveOnly(MoveOnly&& x) : data_(x.data_) { + x.data_ = 0; + } + + MoveOnly& operator=(MoveOnly&& x) { + data_ = x.data_; + x.data_ = 0; + return *this; + } + + int get() const { + return data_; + } + bool operator==(const MoveOnly& x) const { + return data_ == x.data_; + } + bool operator<(const MoveOnly& x) const { + return data_ < x.data_; + } + }; + + using MoveOnly1 = MoveOnly<1>; + using MoveOnly2 = MoveOnly<2>; +} + +template class Tuple> +static void template_template_test_case() { + { + using T = mpl::tuple<>; + T t0; + T t = std::move(t0); + (void)t; + } + { + using T = mpl::tuple; + T t0(MoveOnly1(0)); + T t = std::move(t0); + (void)t; + REQUIRE(std::get<0>(t) == 0); + } + { + using T = mpl::tuple; + T t0(MoveOnly1(0), MoveOnly2(1)); + T t = std::move(t0); + (void)t; + REQUIRE(std::get<0>(t) == 0); + REQUIRE(std::get<1>(t) == 1); + } + { + // Check for SFINAE-friendliness + STATIC_REQUIRE(!std::is_constructible, MoveOnly1 const&>{}); + + STATIC_REQUIRE(!std::is_constructible, MoveOnly1&>{}); + + STATIC_REQUIRE(std::is_constructible, MoveOnly1>{}); + + STATIC_REQUIRE(std::is_constructible, MoveOnly2&&>{}); + } +} + +TEST_CASE("tuple - move construction") { + { + INFO("mpl::tuple"); + template_template_test_case(); + } + { + INFO("mpl::uple"); + template_template_test_case(); + } +} diff --git a/tests/functional/tuple/cnstr.nested.cpp b/tests/functional/tuple/cnstr.nested.cpp new file mode 100644 index 000000000..f50c714a6 --- /dev/null +++ b/tests/functional/tuple/cnstr.nested.cpp @@ -0,0 +1,23 @@ +#include +#include + +using namespace sqlite_orm; + +// See this bug: https://llvm.org/bugs/show_bug.cgi?id=24173 + +namespace { + template + constexpr mpl::tuple...> f(X&&... xs) { + return mpl::tuple...>{std::forward(xs)...}; + } + + template + constexpr mpl::uple...> g(X&&... xs) { + return mpl::uple...>{std::forward(xs)...}; + } +} + +TEST_CASE("tuple - nested") { + f(f(f(f(f(f(f(f(f(f(f(f(1)))))))))))); + g(g(g(g(g(g(g(g(g(g(g(g(1)))))))))))); +} diff --git a/tests/functional/tuple/cnstr.trap.cpp b/tests/functional/tuple/cnstr.trap.cpp new file mode 100644 index 000000000..6854905cb --- /dev/null +++ b/tests/functional/tuple/cnstr.trap.cpp @@ -0,0 +1,87 @@ +#include +#include + +using namespace sqlite_orm; + +// Make sure that the tuple(Yn&&...) is not preferred over copy constructors +// in single-element cases and other similar cases. + +namespace { + struct Trap1 { + Trap1() = default; + Trap1(Trap1 const&) = default; +#ifndef SQLITE_ORM_WORKAROUND_MSVC_MULTIPLECTOR_106654 + Trap1(Trap1&) = default; +#endif + Trap1(Trap1&&) = default; + + template + Trap1(X&&) { + static_assert(sizeof(X) && false, "this constructor must not be instantiated"); + } + }; + + struct Trap2 { + Trap2() = default; + Trap2(Trap2 const&) = default; +#ifndef SQLITE_ORM_WORKAROUND_MSVC_MULTIPLECTOR_106654 + Trap2(Trap2&) = default; +#endif + Trap2(Trap2&&) = default; + + template + Trap2(X) { // not by reference + static_assert(sizeof(X) && false, "this constructor must not be instantiated"); + } + }; + + struct Trap3 { + Trap3() = default; + Trap3(Trap3 const&) = default; +#ifndef SQLITE_ORM_WORKAROUND_MSVC_MULTIPLECTOR_106654 + Trap3(Trap3&) = default; +#endif + Trap3(Trap3&&) = default; + + template + constexpr explicit Trap3(X&&) { // explicit, and constexpr + static_assert(sizeof(X) && false, "this constructor must not be instantiated"); + } + }; + + struct Trap4 { + Trap4() = default; + template + constexpr explicit Trap4(Args&&) { + static_assert(sizeof(Args) && false, "must never be instantiated"); + } + + Trap4(Trap4 const&) = default; + Trap4(Trap4&&) = default; + }; +} + +TEMPLATE_PRODUCT_TEST_CASE("tuple - constructors trap", + "[tuple][trap]", + (mpl::tuple, mpl::uple), + (Trap1, Trap2, Trap3)) { + TestType tuple{}; + TestType implicit_copy = tuple; + TestType explicit_copy(tuple); + TestType implicit_move = std::move(tuple); + TestType explicit_move(std::move(tuple)); + + (void)implicit_copy; + (void)explicit_copy; + (void)implicit_move; + (void)explicit_move; +} + +TEMPLATE_PRODUCT_TEST_CASE("tuple - element constructor trap", "[tuple]", (mpl::tuple, mpl::uple), (Trap4)) { + struct Foo { + Foo() = default; + Foo(Foo const&) = default; + Foo(Foo&&) = default; + TestType t; + }; +} diff --git a/tests/functional/tuple/cnstr.variadic_array.cpp b/tests/functional/tuple/cnstr.variadic_array.cpp new file mode 100644 index 000000000..31a011d5a --- /dev/null +++ b/tests/functional/tuple/cnstr.variadic_array.cpp @@ -0,0 +1,17 @@ +#include +#include +#include + +using namespace sqlite_orm; + +// +// This test checks that we can NOT construct a tuple holding array members, +// per the standard. +// + +TEST_CASE("tuple - array elements") { + STATIC_REQUIRE(!std::is_constructible, int[3]>{}); + STATIC_REQUIRE(!std::is_constructible, int[3], float[4]>{}); + STATIC_REQUIRE(!std::is_constructible, int[3]>{}); + STATIC_REQUIRE(!std::is_constructible, int[3], float[4]>{}); +} diff --git a/tests/functional/tuple/cnstr.variadic_copy.cpp b/tests/functional/tuple/cnstr.variadic_copy.cpp new file mode 100644 index 000000000..7460b4a06 --- /dev/null +++ b/tests/functional/tuple/cnstr.variadic_copy.cpp @@ -0,0 +1,144 @@ +#include +#include + +using namespace sqlite_orm; + +namespace { + template + struct never { + static constexpr bool value = false; + }; + + struct NoValueCtor { + NoValueCtor() : id(++count) {} + NoValueCtor(NoValueCtor const& other) : id(other.id) { + ++count; + } + + // The constexpr is required to make is_constructible instantiate this + // template. The explicit is needed to test-around a similar bug with + // is_convertible. + template + constexpr explicit NoValueCtor(T) { + static_assert(never::value, "This should not be instantiated"); + } + + static int count; + int id; + }; + + int NoValueCtor::count = 0; + + struct NoValueCtorEmpty { + NoValueCtorEmpty() {} + NoValueCtorEmpty(NoValueCtorEmpty const&) {} + + template + constexpr explicit NoValueCtorEmpty(T) { + static_assert(never::value, "This should not be instantiated"); + } + }; +} + +template class Tuple> +static void template_template_test_case() { + { + Tuple t(2); + REQUIRE(std::get<0>(t) == 2); + } + { + constexpr Tuple t(2); + STATIC_REQUIRE(std::get<0>(t) == 2); + } + { + constexpr Tuple t; + STATIC_REQUIRE(std::get<0>(t) == 0); + } + { + constexpr Tuple t(2, nullptr); + STATIC_REQUIRE(std::get<0>(t) == 2); + STATIC_REQUIRE(std::get<1>(t) == nullptr); + } + { + Tuple t(2, nullptr); + REQUIRE(std::get<0>(t) == 2); + REQUIRE(std::get<1>(t) == nullptr); + } + { + Tuple t(2, nullptr, "text"); + REQUIRE(std::get<0>(t) == 2); + REQUIRE(std::get<1>(t) == nullptr); + REQUIRE(std::get<2>(t) == "text"); + } + { + Tuple t(1, NoValueCtor(), 2, 3); + REQUIRE(std::get<0>(t) == 1); + REQUIRE(std::get<1>(t).id == NoValueCtor::count - 1); + REQUIRE(std::get<2>(t) == 2); + REQUIRE(std::get<3>(t) == 3); + } + { + Tuple t(1, NoValueCtorEmpty(), 2, 3); + REQUIRE(std::get<0>(t) == 1); + REQUIRE(std::get<2>(t) == 2); + REQUIRE(std::get<3>(t) == 3); + } + { + struct T {}; + struct U {}; + struct V {}; + + constexpr T t{}; + constexpr U u{}; + constexpr V v{}; + + constexpr Tuple x1{t}; + (void)x1; + constexpr Tuple x2{t, u}; + (void)x2; + constexpr Tuple x3{t, u, v}; + (void)x3; + } + { + struct T {}; + struct U {}; + struct V {}; + + // Check for SFINAE-friendliness + STATIC_REQUIRE(!std::is_constructible, T>{}); + + STATIC_REQUIRE(!std::is_constructible, U, T>{}); + + STATIC_REQUIRE(!std::is_constructible, T, U, V>{}); + } + + // Make sure we can initialize elements with the brace-init syntax. + { + struct Member {}; + struct Element { + Member member; + }; + struct Element2 { + Member member; + }; + struct Element3 { + Member member; + }; + + Tuple xs{{Member()}, {Member()}, {Member()}}; + Tuple ys = {{Member()}, {Member()}, {Member()}}; + (void)xs; + (void)ys; + } +} + +TEST_CASE("tuple - variadic copy") { + { + INFO("mpl::tuple"); + template_template_test_case(); + } + { + INFO("mpl::uple"); + template_template_test_case(); + } +} diff --git a/tests/functional/tuple/cnstr.variadic_forward.cpp b/tests/functional/tuple/cnstr.variadic_forward.cpp new file mode 100644 index 000000000..24b3025e9 --- /dev/null +++ b/tests/functional/tuple/cnstr.variadic_forward.cpp @@ -0,0 +1,98 @@ +#include +#include + +using namespace sqlite_orm; + +namespace { + struct MoveOnly { + int data_; + MoveOnly(MoveOnly const&) = delete; + MoveOnly& operator=(MoveOnly const&) = delete; + MoveOnly(int data = 1) : data_(data) {} + MoveOnly(MoveOnly&& x) : data_(x.data_) { + x.data_ = 0; + } + + MoveOnly& operator=(MoveOnly&& x) { + data_ = x.data_; + x.data_ = 0; + return *this; + } + + int get() const { + return data_; + } + bool operator==(const MoveOnly& x) const { + return data_ == x.data_; + } + bool operator<(const MoveOnly& x) const { + return data_ < x.data_; + } + }; + + struct Empty {}; + struct A { + int id_; + explicit constexpr A(int i) : id_(i) {} + }; + + struct NoDefault { + NoDefault() = delete; + }; +} + +TEST_CASE("tuple - variadic forward") { + { + mpl::tuple t(MoveOnly(0)); + REQUIRE(std::get<0>(t) == 0); + } + { + mpl::tuple t(MoveOnly(0), MoveOnly(1)); + REQUIRE(std::get<0>(t) == 0); + REQUIRE(std::get<1>(t) == 1); + } + { + mpl::tuple t(MoveOnly(0), MoveOnly(1), MoveOnly(2)); + REQUIRE(std::get<0>(t) == 0); + REQUIRE(std::get<1>(t) == 1); + REQUIRE(std::get<2>(t) == 2); + } + { + constexpr mpl::tuple t0{Empty()}; + (void)t0; + } + { + constexpr mpl::tuple t(3, 2); + STATIC_REQUIRE(std::get<0>(t).id_ == 3); + } + { + typedef mpl::tuple Tuple; + + STATIC_REQUIRE(!std::is_constructible::value); + + STATIC_REQUIRE(std::is_constructible::value); + } + { + typedef mpl::tuple Tuple; + + STATIC_REQUIRE(!std::is_constructible::value); + + STATIC_REQUIRE(std::is_constructible::value); + } + { + typedef mpl::tuple Tuple; + typedef mpl::tuple NestedTuple; + + STATIC_REQUIRE(!std::is_constructible::value); + + STATIC_REQUIRE(std::is_constructible::value); + } + { + typedef mpl::tuple Tuple; + typedef mpl::tuple NestedTuple; + + STATIC_REQUIRE(!std::is_constructible::value); + + STATIC_REQUIRE(std::is_constructible::value); + } +} diff --git a/tests/functional/tuple/empty_member.cpp b/tests/functional/tuple/empty_member.cpp new file mode 100644 index 000000000..e2bec6af3 --- /dev/null +++ b/tests/functional/tuple/empty_member.cpp @@ -0,0 +1,16 @@ +#include +#include + +using namespace sqlite_orm; + +namespace { + struct A {}; + struct B {}; +} + +TEMPLATE_PRODUCT_TEST_CASE("tuple - empty member", + "[tuple]", + (mpl::tuple, mpl::uple), + ((int, A), (A, int), (A, int, B), (A, B, int), (int, A, B))) { + STATIC_REQUIRE(sizeof(TestType) == sizeof(int)); +} diff --git a/tests/pointer_passing_interface.cpp b/tests/pointer_passing_interface.cpp index 529371286..48877800f 100644 --- a/tests/pointer_passing_interface.cpp +++ b/tests/pointer_passing_interface.cpp @@ -29,6 +29,8 @@ namespace { } TEST_CASE("pointer-passing") { + polyfill::conjunction_v>; + polyfill::conjunction_v>>; // accept and return a pointer of type "carray" struct pass_thru_pointer_fn { using bindable_carray_ptr_t = static_carray_pointer_binding; diff --git a/tests/statement_serializer_tests/bindables.cpp b/tests/statement_serializer_tests/bindables.cpp index 2f4f59e43..8f6b4d6fd 100644 --- a/tests/statement_serializer_tests/bindables.cpp +++ b/tests/statement_serializer_tests/bindables.cpp @@ -1,6 +1,5 @@ #include #include -#include #include // std::fill_n #include #include @@ -12,7 +11,6 @@ using std::make_index_sequence; using std::nullptr_t; using std::shared_ptr; using std::string; -using std::tuple; using std::tuple_element_t; using std::tuple_size; using std::unique_ptr; @@ -91,8 +89,8 @@ void require_strings(const array& values, } template -void test_tuple(const tuple& t, const Ctx& ctx, const array& expected) { - require_strings({internal::serialize(get(t), ctx)...}, expected, index_sequence_for{}); +void test_tuple(const mpl::uple& t, const Ctx& ctx, const array& expected) { + require_strings({internal::serialize(std::get(t), ctx)...}, expected, index_sequence_for{}); } namespace { @@ -126,32 +124,32 @@ TEST_CASE("bindables") { context_t context{dbObjects}; SECTION("bindable_builtin_types") { - using Tuple = tuple; + >; constexpr Tuple tpl = make_default_tuple(); @@ -192,33 +190,33 @@ TEST_CASE("bindables") { } SECTION("non-bindable literals") { context.replace_bindable_with_question = true; - constexpr auto t = make_default_tuple>(); + constexpr auto t = make_default_tuple>(); test_tuple(t, context, e); } } SECTION("bindable_types") { - using Tuple = tuple, + wstring, + StringVeneer, #endif - unique_ptr, - shared_ptr, - vector, + unique_ptr, + shared_ptr, + vector, #ifdef SQLITE_ORM_OPTIONAL_SUPPORTED - std::optional, - std::optional, + std::optional, + std::optional, #endif #ifdef SQLITE_ORM_STRING_VIEW_SUPPORTED - std::string_view, + std::string_view, #ifndef SQLITE_ORM_OMITS_CODECVT - std::wstring_view, + std::wstring_view, #endif #endif - StringVeneer, - Custom, - unique_ptr>; + StringVeneer, + Custom, + unique_ptr>; Tuple tpl = make_default_tuple(); @@ -254,7 +252,7 @@ TEST_CASE("bindables") { } SECTION("non-bindable literals") { context.replace_bindable_with_question = true; - auto t = make_default_tuple>(); + auto t = make_default_tuple>(); test_tuple(t, context, e); } } diff --git a/tests/static_tests/bindable_filter.cpp b/tests/static_tests/bindable_filter.cpp index a58676f02..c2995c4bc 100644 --- a/tests/static_tests/bindable_filter.cpp +++ b/tests/static_tests/bindable_filter.cpp @@ -27,62 +27,62 @@ TEST_CASE("bindable_filter") { using internal::bindable_filter_t; using std::is_same; { - using Tuple = std::tuple, + using Tuple = mpl::uple, #ifndef SQLITE_ORM_OMITS_CODECVT - const wchar_t*, - std::wstring, - StringVeneer, + const wchar_t*, + std::wstring, + StringVeneer, #endif - std::vector, - std::nullptr_t, + std::vector, + std::nullptr_t, #ifdef SQLITE_ORM_OPTIONAL_SUPPORTED - std::nullopt_t, - std::optional, - std::optional, + std::nullopt_t, + std::optional, + std::optional, #endif #ifdef SQLITE_ORM_STRING_VIEW_SUPPORTED - std::string_view, + std::string_view, #ifndef SQLITE_ORM_OMITS_CODECVT - std::wstring_view, + std::wstring_view, #endif #endif - std::unique_ptr, - std::shared_ptr, + std::unique_ptr, + std::shared_ptr, #ifdef SQLITE_ORM_INLINE_VARIABLES_SUPPORTED - static_pointer_binding, + static_pointer_binding, #endif - Custom, - std::unique_ptr>; + Custom, + std::unique_ptr>; using Res = bindable_filter_t; STATIC_REQUIRE(is_same::value); } { - using Tuple = std::tuple; + using Tuple = mpl::uple; using Res = bindable_filter_t; - using Expected = std::tuple; + using Expected = mpl::uple; STATIC_REQUIRE(is_same::value); } { - using Tuple = std::tuple; + using Tuple = mpl::uple; using Res = bindable_filter_t; - using Expected = std::tuple; + using Expected = mpl::uple; STATIC_REQUIRE(is_same::value); } } diff --git a/tests/static_tests/foreign_key.cpp b/tests/static_tests/foreign_key.cpp index a5fdc8956..f7a9149ea 100644 --- a/tests/static_tests/foreign_key.cpp +++ b/tests/static_tests/foreign_key.cpp @@ -3,7 +3,6 @@ #include // std::is_same #include // std::string -#include // std::is_same #include "static_tests_storage_traits.h" @@ -106,32 +105,32 @@ TEST_CASE("foreign key static") { using namespace sqlite_orm::internal::storage_traits; { using FkTuple = storage_fk_references::type; - using Expected = std::tuple<>; + using Expected = mpl::tuple<>; STATIC_REQUIRE(std::is_same::value); } { using FkTuple = storage_fk_references::type; - using Expected = std::tuple; + using Expected = mpl::tuple; STATIC_REQUIRE(std::is_same::value); } { using FkTuple = storage_fk_references::type; - using Expected = std::tuple<>; + using Expected = mpl::tuple<>; STATIC_REQUIRE(std::is_same::value); } { using FkTuple = storage_fk_references::type; - using Expected = std::tuple<>; + using Expected = mpl::tuple<>; STATIC_REQUIRE(std::is_same::value); } { using FkTuple = storage_fk_references::type; - using Expected = std::tuple<>; + using Expected = mpl::tuple<>; STATIC_REQUIRE(std::is_same::value); } { using FkTuple = storage_fk_references::type; - using Expected = std::tuple; + using Expected = mpl::tuple; STATIC_REQUIRE(std::is_same::value); } } diff --git a/tests/static_tests/function_static_tests.cpp b/tests/static_tests/function_static_tests.cpp index 44790b948..c82956a59 100644 --- a/tests/static_tests/function_static_tests.cpp +++ b/tests/static_tests/function_static_tests.cpp @@ -43,12 +43,12 @@ TEST_CASE("function static") { STATIC_REQUIRE(std::is_same::value); using ArgumentsTuple = internal::member_function_arguments::tuple_type; - using ExpectedArgumentsTuple = std::tuple; + using ExpectedArgumentsTuple = mpl::tuple; STATIC_REQUIRE(std::is_same::value); STATIC_REQUIRE(std::is_same::return_type, double>::value); STATIC_REQUIRE( - std::is_same::args_tuple, std::tuple>::value); + std::is_same::args_tuple, mpl::tuple>::value); } SECTION("double(double)") { struct Function { @@ -65,12 +65,12 @@ TEST_CASE("function static") { STATIC_REQUIRE(std::is_same::value); using ArgumentsTuple = internal::member_function_arguments::tuple_type; - using ExpectedArgumentsTuple = std::tuple; + using ExpectedArgumentsTuple = mpl::tuple; STATIC_REQUIRE(std::is_same::value); STATIC_REQUIRE(std::is_same::return_type, double>::value); STATIC_REQUIRE( - std::is_same::args_tuple, std::tuple>::value); + std::is_same::args_tuple, mpl::tuple>::value); } SECTION("int(std::string) const") { struct Function { @@ -87,12 +87,12 @@ TEST_CASE("function static") { STATIC_REQUIRE(std::is_same::value); using ArgumentsTuple = internal::member_function_arguments::tuple_type; - using ExpectedArgumentsTuple = std::tuple; + using ExpectedArgumentsTuple = mpl::tuple; STATIC_REQUIRE(std::is_same::value); STATIC_REQUIRE(std::is_same::return_type, int>::value); STATIC_REQUIRE( - std::is_same::args_tuple, std::tuple>::value); + std::is_same::args_tuple, mpl::tuple>::value); } SECTION("int(std::string)") { struct Function { @@ -109,12 +109,12 @@ TEST_CASE("function static") { STATIC_REQUIRE(std::is_same::value); using ArgumentsTuple = internal::member_function_arguments::tuple_type; - using ExpectedArgumentsTuple = std::tuple; + using ExpectedArgumentsTuple = mpl::tuple; STATIC_REQUIRE(std::is_same::value); STATIC_REQUIRE(std::is_same::return_type, int>::value); STATIC_REQUIRE( - std::is_same::args_tuple, std::tuple>::value); + std::is_same::args_tuple, mpl::tuple>::value); } SECTION("std::string(const std::string &, const std::string &) const") { struct Function { @@ -131,12 +131,12 @@ TEST_CASE("function static") { STATIC_REQUIRE(std::is_same::value); using ArgumentsTuple = internal::member_function_arguments::tuple_type; - using ExpectedArgumentsTuple = std::tuple; + using ExpectedArgumentsTuple = mpl::tuple; STATIC_REQUIRE(std::is_same::value); STATIC_REQUIRE(std::is_same::return_type, std::string>::value); STATIC_REQUIRE(std::is_same::args_tuple, - std::tuple>::value); + mpl::tuple>::value); } SECTION("std::string(const std::string &, const std::string &)") { struct Function { @@ -153,12 +153,12 @@ TEST_CASE("function static") { STATIC_REQUIRE(std::is_same::value); using ArgumentsTuple = internal::member_function_arguments::tuple_type; - using ExpectedArgumentsTuple = std::tuple; + using ExpectedArgumentsTuple = mpl::tuple; STATIC_REQUIRE(std::is_same::value); STATIC_REQUIRE(std::is_same::return_type, std::string>::value); STATIC_REQUIRE(std::is_same::args_tuple, - std::tuple>::value); + mpl::tuple>::value); } } } @@ -190,7 +190,7 @@ TEST_CASE("function static") { STATIC_REQUIRE(std::is_same::value); STATIC_REQUIRE(std::is_same::return_type, int>::value); - STATIC_REQUIRE(std::is_same::args_tuple, std::tuple>::value); + STATIC_REQUIRE(std::is_same::args_tuple, mpl::tuple>::value); } SECTION("void(std::string) const & std::string()") { struct Function { @@ -218,7 +218,7 @@ TEST_CASE("function static") { STATIC_REQUIRE(std::is_same::return_type, std::string>::value); STATIC_REQUIRE( - std::is_same::args_tuple, std::tuple>::value); + std::is_same::args_tuple, mpl::tuple>::value); } } } diff --git a/tests/static_tests/functional/tuple_conc.cpp b/tests/static_tests/functional/tuple_conc.cpp index f55f5bea4..076e3ef49 100644 --- a/tests/static_tests/functional/tuple_conc.cpp +++ b/tests/static_tests/functional/tuple_conc.cpp @@ -4,56 +4,57 @@ #include // std::is_same using namespace sqlite_orm; +using mpl::tuple; TEST_CASE("Tuple conc") { using namespace internal; { - using TupleL = std::tuple; - using TupleR = std::tuple; + using TupleL = tuple; + using TupleR = tuple; using IntStringTuple = tuple_cat_t; - STATIC_REQUIRE(std::is_same>::value); + STATIC_REQUIRE(std::is_same>::value); } { - using TupleL = std::tuple; - using TupleR = std::tuple; + using TupleL = tuple; + using TupleR = tuple; using IntFloatTuple = tuple_cat_t; - STATIC_REQUIRE(std::is_same>::value); + STATIC_REQUIRE(std::is_same>::value); } { - using TupleL = std::tuple<>; - using TupleR = std::tuple; + using TupleL = tuple<>; + using TupleR = tuple; using NoneFloatTuple = tuple_cat_t; - STATIC_REQUIRE(std::is_same>::value); + STATIC_REQUIRE(std::is_same>::value); } { - using TupleL = std::tuple<>; - using TupleR = std::tuple<>; + using TupleL = tuple<>; + using TupleR = tuple<>; using NoneNoneTuple = tuple_cat_t; - STATIC_REQUIRE(std::is_same>::value); + STATIC_REQUIRE(std::is_same>::value); } { - using TupleL = std::tuple; - using TupleR = std::tuple; + using TupleL = tuple; + using TupleR = tuple; using IntFloatDoubleTuple = tuple_cat_t; - STATIC_REQUIRE(std::is_same>::value); + STATIC_REQUIRE(std::is_same>::value); } { - using Arg = std::tuple; + using Arg = tuple; using SingleArgTuple = tuple_cat_t; STATIC_REQUIRE(std::is_same::value); } { - using Arg1 = std::tuple; - using Arg2 = std::tuple; - using Arg3 = std::tuple; + using Arg1 = tuple; + using Arg2 = tuple; + using Arg3 = tuple; using IntFloatStringTuple = tuple_cat_t; - STATIC_REQUIRE(std::is_same>::value); + STATIC_REQUIRE(std::is_same>::value); } { - using Arg1 = std::tuple; - using Arg2 = std::tuple; - using Arg3 = std::tuple<>; + using Arg1 = tuple; + using Arg2 = tuple; + using Arg3 = tuple<>; using IntFloatEmptyTuple = tuple_cat_t; - STATIC_REQUIRE(std::is_same>::value); + STATIC_REQUIRE(std::is_same>::value); } } diff --git a/tests/static_tests/functional/tuple_filter.cpp b/tests/static_tests/functional/tuple_filter.cpp index 552c8c122..956ab6639 100644 --- a/tests/static_tests/functional/tuple_filter.cpp +++ b/tests/static_tests/functional/tuple_filter.cpp @@ -3,7 +3,6 @@ #include // std::is_same using namespace sqlite_orm; -using std::make_tuple; namespace { struct User { @@ -15,8 +14,8 @@ namespace { TEST_CASE("tuple_filter") { using internal::filter_tuple_t; SECTION("is_bindable") { - using Arg = std::tuple, internal::order_by_t>; - using Expected = std::tuple; + using Arg = mpl::tuple, internal::order_by_t>; + using Expected = mpl::tuple; using ResultType = filter_tuple_t; STATIC_REQUIRE(std::is_same::value); } @@ -25,8 +24,8 @@ TEST_CASE("tuple_filter") { using Column = decltype(column); using OrderBy = internal::order_by_t; using Unique = decltype(unique(&User::id)); - using Arg = std::tuple; - using Expected = std::tuple; + using Arg = mpl::tuple; + using Expected = mpl::tuple; using ResultType = filter_tuple_t; STATIC_REQUIRE(std::is_same::value); } @@ -35,7 +34,7 @@ TEST_CASE("tuple_filter") { TEST_CASE("count_tuple") { using internal::count_tuple; { - auto t = make_tuple(where(is_equal(&User::id, 5)), limit(5), order_by(&User::name)); + auto t = mpl::make_tuple(where(is_equal(&User::id, 5)), limit(5), order_by(&User::name)); using T = decltype(t); STATIC_REQUIRE(count_tuple::value == 1); STATIC_REQUIRE(count_tuple::value == 0); @@ -43,8 +42,9 @@ TEST_CASE("count_tuple") { STATIC_REQUIRE(count_tuple::value == 1); } { - auto t = - make_tuple(where(lesser_than(&User::id, 10)), where(greater_than(&User::id, 5)), group_by(&User::name)); + auto t = mpl::make_tuple(where(lesser_than(&User::id, 10)), + where(greater_than(&User::id, 5)), + group_by(&User::name)); using T = decltype(t); STATIC_REQUIRE(count_tuple::value == 2); STATIC_REQUIRE(count_tuple::value == 1); @@ -52,7 +52,7 @@ TEST_CASE("count_tuple") { STATIC_REQUIRE(count_tuple::value == 0); } { - auto t = make_tuple(group_by(&User::name), limit(10, offset(5))); + auto t = mpl::make_tuple(group_by(&User::name), limit(10, offset(5))); using T = decltype(t); STATIC_REQUIRE(count_tuple::value == 0); STATIC_REQUIRE(count_tuple::value == 1); @@ -60,7 +60,8 @@ TEST_CASE("count_tuple") { STATIC_REQUIRE(count_tuple::value == 1); } { - auto t = make_tuple(where(is_null(&User::name)), order_by(&User::id), multi_order_by(order_by(&User::name))); + auto t = + mpl::make_tuple(where(is_null(&User::name)), order_by(&User::id), multi_order_by(order_by(&User::name))); using T = decltype(t); STATIC_REQUIRE(count_tuple::value == 1); STATIC_REQUIRE(count_tuple::value == 0); @@ -68,7 +69,7 @@ TEST_CASE("count_tuple") { STATIC_REQUIRE(count_tuple::value == 0); } { - auto t = make_tuple(dynamic_order_by(make_storage(""))); + auto t = mpl::make_tuple(dynamic_order_by(make_storage(""))); using T = decltype(t); STATIC_REQUIRE(count_tuple::value == 0); STATIC_REQUIRE(count_tuple::value == 0); diff --git a/tests/static_tests/functional/tuple_traits.cpp b/tests/static_tests/functional/tuple_traits.cpp index f8690170b..9c82d1d12 100644 --- a/tests/static_tests/functional/tuple_traits.cpp +++ b/tests/static_tests/functional/tuple_traits.cpp @@ -10,8 +10,8 @@ using internal::is_primary_key; using internal::primary_key_t; TEST_CASE("tuple traits") { - using empty_tuple_type = std::tuple<>; - using tuple_type = std::tuple, primary_key_t<>, std::string>; + using empty_tuple_type = mpl::tuple<>; + using tuple_type = mpl::tuple, primary_key_t<>, std::string>; STATIC_REQUIRE(mpl::invoke_t, tuple_type>::value); STATIC_REQUIRE(mpl::invoke_t, tuple_type>::value); diff --git a/tests/static_tests/is_column_with_insertable_primary_key.cpp b/tests/static_tests/is_column_with_insertable_primary_key.cpp index 9f0b15f27..050e63881 100644 --- a/tests/static_tests/is_column_with_insertable_primary_key.cpp +++ b/tests/static_tests/is_column_with_insertable_primary_key.cpp @@ -23,17 +23,17 @@ TEST_CASE("is_column_with_insertable_primary_key") { bool isActive; }; - auto insertable = std::make_tuple( /// + auto insertable = mpl::make_tuple( /// make_column("", &User::id, primary_key()), make_column("", &User::username, primary_key(), default_value("Clint Eastwood")), make_column("", &User::username, primary_key(), default_value(std::vector{})), make_column("", &User::username, primary_key(), autoincrement())); - auto noninsertable = std::make_tuple( /// + auto noninsertable = mpl::make_tuple( /// make_column("", &User::username, primary_key()), make_column("", &User::password, primary_key())); - auto outside = std::make_tuple( /// + auto outside = mpl::make_tuple( /// make_column("", &User::id), ///< not a primary key std::make_shared() ///< not a column ); diff --git a/tests/static_tests/node_tuple.cpp b/tests/static_tests/node_tuple.cpp index c0dca0a4b..34557ad18 100644 --- a/tests/static_tests/node_tuple.cpp +++ b/tests/static_tests/node_tuple.cpp @@ -14,14 +14,14 @@ template struct is_tuple : std::false_type {}; template -struct is_tuple> : std::true_type {}; +struct is_tuple> : std::true_type {}; TEST_CASE("Node tuple") { using internal::bindable_filter_t; using internal::node_tuple; using internal::node_tuple_t; + using mpl::tuple; using std::is_same; - using std::tuple; struct User { int id = 0; @@ -463,7 +463,7 @@ TEST_CASE("Node tuple") { where(greater_or_equal(&User::id, 10) and lesser_or_equal(&User::id, 20))); using Sel = decltype(sel); using Tuple = node_tuple_t; - using Expected = std:: + using Expected = tuple; static_assert(is_same::value, "select(columns(&User::id, &User::name), where(greater_or_equal(&User::id, 10) and " @@ -869,8 +869,8 @@ TEST_CASE("Node tuple") { using CaseExpressionTuple = node_tuple::type; STATIC_REQUIRE(is_same>::value); - STATIC_REQUIRE(is_tuple>::value); - STATIC_REQUIRE(is_tuple>::value); + STATIC_REQUIRE(is_tuple>::value); + STATIC_REQUIRE(is_tuple>::value); STATIC_REQUIRE(!is_tuple::value); STATIC_REQUIRE(is_pair>::value); STATIC_REQUIRE(!is_pair::value); @@ -885,7 +885,7 @@ TEST_CASE("Node tuple") { STATIC_REQUIRE(is_same::value); using Arg0Second = Arg0::second_type; STATIC_REQUIRE(is_same::value); - STATIC_REQUIRE(is_same>>::value); + STATIC_REQUIRE(is_same>>::value); using ElseExpressionTuple = node_tuple::type; STATIC_REQUIRE(is_same>::value); diff --git a/tests/static_tests/static_tests_storage_traits.h b/tests/static_tests/static_tests_storage_traits.h index b5247aae6..032398ebb 100644 --- a/tests/static_tests/static_tests_storage_traits.h +++ b/tests/static_tests/static_tests_storage_traits.h @@ -7,8 +7,6 @@ #include // std::integral_constant -#include - namespace sqlite_orm { namespace internal { @@ -103,11 +101,11 @@ namespace sqlite_orm { template struct storage_fk_references_impl, Lookup> - : conc_tuple::type...> {}; + : mpl::flatten_types::type...> {}; template struct storage_foreign_keys_impl, Lookup> - : conc_tuple...> {}; + : mpl::flatten_types...> {}; /** * S - storage class diff --git a/tests/tuple_iteration.cpp b/tests/tuple_iteration.cpp index aa8be2866..6a1859e2b 100644 --- a/tests/tuple_iteration.cpp +++ b/tests/tuple_iteration.cpp @@ -16,22 +16,22 @@ TEST_CASE("tuple iteration") { types.emplace_back(typeid(item)); }; SECTION("empty") { - std::tuple<> tuple; + mpl::tuple<> tuple; iterate_tuple(tuple, lambda); } SECTION("int") { - std::tuple tuple; + mpl::tuple tuple; iterate_tuple(tuple, lambda); expected = {typeid(int)}; } SECTION("std::string, long") { - std::tuple tuple; + mpl::tuple tuple; iterate_tuple(tuple, lambda); expected = {typeid(std::string), typeid(long)}; } SECTION("index selection") { constexpr size_t selectedIdx = 1; - std::tuple tuple; + mpl::tuple tuple; iterate_tuple(tuple, std::index_sequence{}, lambda); expected = {typeid(long)}; } @@ -42,14 +42,14 @@ TEST_CASE("tuple iteration") { types.emplace_back(typeid(Item)); }; SECTION("empty") { - iterate_tuple>(lambda); + iterate_pack(mpl::pack<>{}, lambda); } SECTION("int") { - iterate_tuple>(lambda); + iterate_pack(mpl::pack{}, lambda); expected = {typeid(int)}; } SECTION("std::string, long") { - iterate_tuple>(lambda); + iterate_pack(mpl::pack{}, lambda); expected = {typeid(std::string), typeid(long)}; } } @@ -60,7 +60,7 @@ TEST_CASE("creation from tuple") { using namespace internal; using Catch::Matchers::Equals; - std::tuple tpl{"abc", "xyz"}; + mpl::tuple tpl{"abc", "xyz"}; SECTION("identity") { std::vector expected{get<0>(tpl), get<1>(tpl)}; auto strings = create_from_tuple>(tpl);