From 443614a0e7e3aa7ee8c2ef62885175b9e6e9a5ed Mon Sep 17 00:00:00 2001 From: rbock Date: Thu, 27 Nov 2014 22:16:12 +0100 Subject: [PATCH] Reduced compiler error spew dramatically for from and having. --- include/sqlpp11/bad_statement.h | 41 ++++++++++++++++++++++++++++ include/sqlpp11/from.h | 27 ++++++++++++------ include/sqlpp11/group_by.h | 34 +++++++++++++---------- include/sqlpp11/having.h | 44 +++++++++++++++++++++--------- include/sqlpp11/order_by.h | 38 +++++++++++++++----------- include/sqlpp11/policy_update.h | 16 +++++++++++ include/sqlpp11/select_flag_list.h | 32 ++++++++++++++-------- include/sqlpp11/sort_order.h | 2 +- 8 files changed, 169 insertions(+), 65 deletions(-) create mode 100644 include/sqlpp11/bad_statement.h diff --git a/include/sqlpp11/bad_statement.h b/include/sqlpp11/bad_statement.h new file mode 100644 index 00000000..16b3f7e4 --- /dev/null +++ b/include/sqlpp11/bad_statement.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2013-2014, Roland Bock + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, this + * list of conditions and the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SQLPP_BAD_STATEMENT_H +#define SQLPP_BAD_STATEMENT_H + +namespace sqlpp +{ + struct bad_statement + { + template + bad_statement(T&&...) {} + }; +} + +#endif + + diff --git a/include/sqlpp11/from.h b/include/sqlpp11/from.h index 1534be1f..6d34b994 100644 --- a/include/sqlpp11/from.h +++ b/include/sqlpp11/from.h @@ -163,33 +163,42 @@ namespace sqlpp struct _methods_t { using _database_t = typename Policies::_database_t; - template - using _new_statement_t = new_statement; + + template + using _check = detail::all_t::value...>; + + template + using _new_statement_t = new_statement_t; using _consistency_check = consistent_t; template auto from(Tables... tables) const - -> _new_statement_t> + -> _new_statement_t<_check, from_t> { + static_assert(_check::value, "at least one argument is not a table or join in from()"); static_assert(sizeof...(Tables), "at least one table or join argument required in from()"); - return _from_impl(tables...); + return _from_impl(_check{}, tables...); } template auto dynamic_from(Tables... tables) const - -> _new_statement_t> + -> _new_statement_t<_check, from_t<_database_t, Tables...>> { static_assert(not std::is_same<_database_t, void>::value, "dynamic_from must not be called in a static statement"); - return _from_impl<_database_t>(tables...); + static_assert(_check::value, "at least one argument is not a table or join in from()"); + return _from_impl<_database_t>(_check{}, tables...); } private: template - auto _from_impl(Tables... tables) const - -> _new_statement_t> + auto _from_impl(const std::false_type&, Tables... tables) const + -> _new_statement_t>; + + template + auto _from_impl(const std::true_type&, Tables... tables) const + -> _new_statement_t> { - static_assert(detail::all_t::value...>::value, "at least one argument is not a table or join in from()"); static_assert(required_tables_of>::size::value == 0, "at least one table depends on another table"); static constexpr std::size_t _number_of_tables = detail::sum(provided_tables_of::size::value...); diff --git a/include/sqlpp11/group_by.h b/include/sqlpp11/group_by.h index 3871d341..acb2833d 100644 --- a/include/sqlpp11/group_by.h +++ b/include/sqlpp11/group_by.h @@ -75,12 +75,6 @@ namespace sqlpp using _is_dynamic = is_database; - static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression (e.g. a column) required in group_by()"); - - static_assert(not detail::has_duplicates::value, "at least one duplicate argument detected in group_by()"); - - static_assert(detail::all_t::value...>::value, "at least one argument is not an expression in group_by()"); - // Data using _data_t = group_by_data_t; @@ -189,20 +183,32 @@ namespace sqlpp using _consistency_check = consistent_t; - template - auto group_by(Args... args) const - -> _new_statement_t> + template + auto group_by(Expressions... expressions) const + -> _new_statement_t> { - return { static_cast&>(*this), group_by_data_t{args...} }; + static_assert(sizeof...(Expressions), "at least one expression (e.g. a column) required in group_by()"); + return _group_by_impl(expressions...); } - template - auto dynamic_group_by(Args... args) const - -> _new_statement_t> + template + auto dynamic_group_by(Expressions... expressions) const + -> _new_statement_t> { static_assert(not std::is_same<_database_t, void>::value, "dynamic_group_by must not be called in a static statement"); - return { static_cast&>(*this), group_by_data_t<_database_t, Args...>{args...} }; + return _group_by_impl<_database_t>(expressions...); } + + private: + template + auto _group_by_impl(Expressions... expressions) const + -> _new_statement_t> + { + static_assert(not detail::has_duplicates::value, "at least one duplicate argument detected in group_by()"); + static_assert(detail::all_t::value...>::value, "at least one argument is not an expression in group_by()"); + + return { static_cast&>(*this), group_by_data_t{expressions...} }; + }; }; }; diff --git a/include/sqlpp11/having.h b/include/sqlpp11/having.h index 96764184..35580118 100644 --- a/include/sqlpp11/having.h +++ b/include/sqlpp11/having.h @@ -74,9 +74,6 @@ namespace sqlpp using _is_dynamic = is_database; - static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression argument required in having()"); - static_assert(detail::all_t::value...>::value, "at least one argument is not an expression in having()"); - // Data using _data_t = having_data_t; @@ -182,25 +179,46 @@ namespace sqlpp struct _methods_t { using _database_t = typename Policies::_database_t; - template - using _new_statement_t = new_statement; + + template + using _check = detail::all_t::value...>; + + template + using _new_statement_t = new_statement_t; using _consistency_check = consistent_t; - template - auto having(Args... args) const - -> _new_statement_t> + template + auto having(Expressions... expressions) const + -> _new_statement_t<_check, having_t> { - return { static_cast&>(*this), having_data_t{args...} }; + static_assert(_check::value, "at least one argument is not an expression in having()"); + static_assert(sizeof...(Expressions), "at least one expression argument required in having()"); + + return _having_impl(_check{}, expressions...); } - template - auto dynamic_having(Args... args) const - -> _new_statement_t> + template + auto dynamic_having(Expressions... expressions) const + -> _new_statement_t<_check, having_t<_database_t, Expressions...>> { + static_assert(_check::value, "at least one argument is not an expression in having()"); static_assert(not std::is_same<_database_t, void>::value, "dynamic_having must not be called in a static statement"); - return { static_cast&>(*this), having_data_t<_database_t, Args...>{args...} }; + return _having_impl<_database_t>(_check{}, expressions...); } + + private: + template + auto _having_impl(const std::false_type&, Expressions... expressions) const + -> bad_statement; + + template + auto _having_impl(const std::true_type&, Expressions... expressions) const + -> _new_statement_t> + { + return { static_cast&>(*this), having_data_t<_database_t, Expressions...>{expressions...} }; + } + }; }; diff --git a/include/sqlpp11/order_by.h b/include/sqlpp11/order_by.h index ca7c0920..e9929aef 100644 --- a/include/sqlpp11/order_by.h +++ b/include/sqlpp11/order_by.h @@ -75,12 +75,6 @@ namespace sqlpp using _is_dynamic = is_database; - static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression (e.g. a column) required in order_by()"); - - static_assert(not detail::has_duplicates::value, "at least one duplicate argument detected in order_by()"); - - static_assert(detail::all_t::value...>::value, "at least one argument is not an expression in order_by()"); - // Data using _data_t = order_by_data_t; @@ -98,12 +92,12 @@ namespace sqlpp void add(Expression expression) { static_assert(_is_dynamic::value, "add() must not be called for static order_by"); - static_assert(is_expression_t::value, "invalid expression argument in order_by::add()"); + static_assert(is_sort_order_t::value, "invalid expression argument in order_by::add()"); static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables::value, "expression uses tables unknown to this statement in order_by::add()"); using _serialize_check = sqlpp::serialize_check_t; _serialize_check::_(); - using ok = detail::all_t<_is_dynamic::value, is_expression_t::value, _serialize_check::type::value>; + using ok = detail::all_t<_is_dynamic::value, is_sort_order_t::value, _serialize_check::type::value>; _add_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert } @@ -189,20 +183,32 @@ namespace sqlpp using _consistency_check = consistent_t; - template - auto order_by(Args... args) const - -> _new_statement_t> + template + auto order_by(Expressions... expressions) const + -> _new_statement_t> { - return { static_cast&>(*this), order_by_data_t{args...} }; + static_assert(sizeof...(Expressions), "at least one expression (e.g. a column) required in order_by()"); + return _order_by_impl(expressions...); } - template - auto dynamic_order_by(Args... args) const - -> _new_statement_t> + template + auto dynamic_order_by(Expressions... expressions) const + -> _new_statement_t> { static_assert(not std::is_same<_database_t, void>::value, "dynamic_order_by must not be called in a static statement"); - return { static_cast&>(*this), order_by_data_t<_database_t, Args...>{args...} }; + return _order_by_impl<_database_t>(expressions...); } + + private: + template + auto _order_by_impl(Expressions... expressions) const + -> _new_statement_t> + { + static_assert(not detail::has_duplicates::value, "at least one duplicate argument detected in order_by()"); + static_assert(detail::all_t::value...>::value, "at least one argument is not an expression in order_by()"); + + return { static_cast&>(*this), order_by_data_t{expressions...} }; + }; }; }; diff --git a/include/sqlpp11/policy_update.h b/include/sqlpp11/policy_update.h index 1afd9c24..68e31ccc 100644 --- a/include/sqlpp11/policy_update.h +++ b/include/sqlpp11/policy_update.h @@ -28,6 +28,7 @@ #define SQLPP_POLICY_UPDATE_H #include +#include namespace sqlpp { @@ -53,6 +54,21 @@ namespace sqlpp template using new_statement = typename Policies::template _new_statement_t; + template + struct new_statement_impl + { + using type = typename Policies::template _new_statement_t; + }; + + template + struct new_statement_impl + { + using type = bad_statement; + }; + + template + using new_statement_t = typename new_statement_impl::type; + } #endif diff --git a/include/sqlpp11/select_flag_list.h b/include/sqlpp11/select_flag_list.h index 78a42e2b..d35c687d 100644 --- a/include/sqlpp11/select_flag_list.h +++ b/include/sqlpp11/select_flag_list.h @@ -64,10 +64,6 @@ namespace sqlpp using _is_dynamic = is_database; - static_assert(not detail::has_duplicates::value, "at least one duplicate argument detected in select flag list"); - - static_assert(detail::all_t::value...>::value, "at least one argument is not a select flag in select flag list"); - // Data using _data_t = select_flag_list_data_t; @@ -175,20 +171,32 @@ namespace sqlpp using _consistency_check = consistent_t; - template - auto flags(Args... args) const - -> _new_statement_t> + template + auto flags(Flags... flags) const + -> _new_statement_t> { - return { static_cast&>(*this), select_flag_list_data_t{args...} }; + return _flags_impl(flags...); } - template - auto dynamic_flags(Args... args) const - -> _new_statement_t> + template + auto dynamic_flags(Flags... flags) const + -> _new_statement_t> { static_assert(not std::is_same<_database_t, void>::value, "dynamic_flags must not be called in a static statement"); - return { static_cast&>(*this), select_flag_list_data_t<_database_t, Args...>{args...} }; + return _flags_impl<_database_t>(flags...); } + + private: + template + auto _flags_impl(Flags... flags) const + -> _new_statement_t> + { + static_assert(detail::all_t::value...>::value, "at least one argument is not a select flag in select flag list"); + static_assert(not detail::has_duplicates::value, "at least one duplicate argument detected in select flag list"); + + return { static_cast&>(*this), select_flag_list_data_t{flags...} }; + } + }; }; diff --git a/include/sqlpp11/sort_order.h b/include/sqlpp11/sort_order.h index edd15269..04cfaab7 100644 --- a/include/sqlpp11/sort_order.h +++ b/include/sqlpp11/sort_order.h @@ -41,7 +41,7 @@ namespace sqlpp template struct sort_order_t { - using _traits = make_traits; + using _traits = make_traits; using _recursive_traits = make_recursive_traits; Expression _expression;