From d35b6f047ce4e99246b7dd38f2ea0d549e18c1ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20Kr=C3=BCger?= Date: Wed, 24 May 2017 01:32:53 +0200 Subject: [PATCH 01/11] Range interface --- hdr/sqlite_modern_cpp.h | 86 ++++++++++++++++++++++++++++++++++++++++- tests/readme_example.cc | 15 +++++++ 2 files changed, 100 insertions(+), 1 deletion(-) diff --git a/hdr/sqlite_modern_cpp.h b/hdr/sqlite_modern_cpp.h index 0d328470..d460db94 100644 --- a/hdr/sqlite_modern_cpp.h +++ b/hdr/sqlite_modern_cpp.h @@ -81,6 +81,7 @@ namespace sqlite { static void iterate(Tuple&, database_binder&) {} }; + class row_iterator; class database_binder { public: @@ -128,6 +129,8 @@ namespace sqlite { execution_started = state; } bool used() const { return execution_started; } + row_iterator begin(); + row_iterator end(); private: std::shared_ptr _db; @@ -312,7 +315,88 @@ namespace sqlite { binder::run(*this, func); }); } + friend class row_iterator; }; + class row_iterator { + public: + class value_type { + public: + value_type(database_binder *_binder): _binder(_binder) {}; + template + value_type &operator >>(T &result) { + get_col_from_db(*_binder, next_index++, result); + return *this; + } + template + value_type &operator >>(std::tuple& values) { + assert(!next_index); + tuple_iterate>::iterate(values, *_binder); + next_index = sizeof...(Types) + 1; + return *this; + } + explicit operator bool() { + return sqlite3_column_count(_binder->_stmt.get()) >= next_index; + } + template + operator Type() { + Type value; + *this >> value; + return value; + } + private: + database_binder *_binder; + int next_index = 0; + }; + using difference_type = std::ptrdiff_t; + using pointer = value_type*; + using reference = value_type&; + using iterator_category = std::input_iterator_tag; + + row_iterator() = default; + explicit row_iterator(database_binder &binder): _binder(&binder) { + _binder->_start_execute(); + ++*this; + } + + reference operator*() const { return value;} + pointer operator->() const { return std::addressof(**this); } + row_iterator &operator++() { + switch(int result = sqlite3_step(_binder->_stmt.get())) { + case SQLITE_ROW: + value = {_binder}; + /* tuple_iterate::iterate(_value, *_binder); */ + break; + case SQLITE_DONE: + _binder = nullptr; + break; + default: + _binder = nullptr; + exceptions::throw_sqlite_error(result, _binder->sql()); + } + return *this; + } + + // Not well-defined + row_iterator operator++(int); + friend inline bool operator ==(const row_iterator &a, const row_iterator &b) { + return a._binder == b._binder; + } + friend inline bool operator !=(const row_iterator &a, const row_iterator &b) { + return !(a==b); + } + + private: + database_binder *_binder = nullptr; + mutable value_type value{_binder}; // mutable, because `changing` the value is just reading it + }; + + inline row_iterator database_binder::begin() { + return row_iterator(*this); + } + + inline row_iterator database_binder::end() { + return row_iterator(); + } namespace sql_function_binder { template< @@ -913,7 +997,7 @@ namespace sqlite { void inline operator++(database_binder& db, int) { db.execute(); } // Convert the rValue binder to a reference and call first op<<, its needed for the call that creates the binder (be carefull of recursion here!) - template database_binder&& operator << (database_binder&& db, const T& val) { db << val; return std::move(db); } + template database_binder operator << (database_binder&& db, const T& val) { db << val; return std::move(db); } namespace sql_function_binder { template diff --git a/tests/readme_example.cc b/tests/readme_example.cc index e903a85f..851587a9 100644 --- a/tests/readme_example.cc +++ b/tests/readme_example.cc @@ -49,6 +49,21 @@ int main() { exit(EXIT_FAILURE); cout << _age << ' ' << _name << ' ' << _weight << endl; }; + for(auto &&row : db << "select age,name,weight from user where age > ? ;" << 21) { + int _age; + string _name; + double _weight; + row >> _age >> _name >> _weight; + if(_age != age || _name != name) + exit(EXIT_FAILURE); + cout << _age << ' ' << _name << ' ' << _weight << endl; + } + + for(std::tuple row : db << "select age,name,weight from user where age > ? ;" << 21) { + if(std::get(row) != age || std::get(row) != name) + exit(EXIT_FAILURE); + cout << std::get(row) << ' ' << std::get(row) << ' ' << std::get(row) << endl; + } // selects the count(*) from user table // note that you can extract a single culumn single row result only to : int,long,long,float,double,string,u16string From 3d7e040b4cb548e0c5c974ae9a178257cf8e389d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20Kr=C3=BCger?= Date: Wed, 24 May 2017 12:20:13 +0200 Subject: [PATCH 02/11] Reimplement execute primitives with iterators --- hdr/sqlite_modern_cpp.h | 47 +++++++++++++++-------------------------- 1 file changed, 17 insertions(+), 30 deletions(-) diff --git a/hdr/sqlite_modern_cpp.h b/hdr/sqlite_modern_cpp.h index d460db94..610e3ce5 100644 --- a/hdr/sqlite_modern_cpp.h +++ b/hdr/sqlite_modern_cpp.h @@ -154,37 +154,9 @@ namespace sqlite { used(true); } - void _extract(std::function call_back) { - int hresult; - _start_execute(); - - while((hresult = sqlite3_step(_stmt.get())) == SQLITE_ROW) { - call_back(); - } + void _extract(std::function call_back); - if(hresult != SQLITE_DONE) { - errors::throw_sqlite_error(hresult, sql()); - } - } - - void _extract_single_value(std::function call_back) { - int hresult; - _start_execute(); - - if((hresult = sqlite3_step(_stmt.get())) == SQLITE_ROW) { - call_back(); - } else if(hresult == SQLITE_DONE) { - throw errors::no_rows("no rows to extract: exactly 1 row expected", sql(), SQLITE_DONE); - } - - if((hresult = sqlite3_step(_stmt.get())) == SQLITE_ROW) { - throw errors::more_rows("not all rows extracted", sql(), SQLITE_ROW); - } - - if(hresult != SQLITE_DONE) { - errors::throw_sqlite_error(hresult, sql()); - } - } + void _extract_single_value(std::function call_back); #ifdef _MSC_VER sqlite3_stmt* _prepare(const std::u16string& sql) { @@ -397,6 +369,21 @@ namespace sqlite { inline row_iterator database_binder::end() { return row_iterator(); } + void database_binder::_extract(std::function call_back) { + for(auto &&row[[maybe_unused]] : *this) + call_back(); + } + + void database_binder::_extract_single_value(std::function call_back) { + auto iter = begin(); + if(iter == end()) + throw errors::no_rows("no rows to extract: exactly 1 row expected", sql(), SQLITE_DONE); + + call_back(); + + if(++iter != end()) + throw errors::more_rows("not all rows extracted", sql(), SQLITE_ROW); + } namespace sql_function_binder { template< From a5f9f6e28932ada7f8d9f53fd4392588f14bb387 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20Kr=C3=BCger?= Date: Wed, 24 May 2017 13:48:45 +0200 Subject: [PATCH 03/11] Fix bugs --- hdr/sqlite_modern_cpp.h | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/hdr/sqlite_modern_cpp.h b/hdr/sqlite_modern_cpp.h index 610e3ce5..ca89125b 100644 --- a/hdr/sqlite_modern_cpp.h +++ b/hdr/sqlite_modern_cpp.h @@ -295,10 +295,16 @@ namespace sqlite { public: value_type(database_binder *_binder): _binder(_binder) {}; template - value_type &operator >>(T &result) { + typename std::enable_if::value, value_type &>::type operator >>(T &result) { get_col_from_db(*_binder, next_index++, result); return *this; } + template::value, value_type &>::type> + operator T() { + T result; + *this >> result; + return result; + } template value_type &operator >>(std::tuple& values) { assert(!next_index); @@ -306,15 +312,15 @@ namespace sqlite { next_index = sizeof...(Types) + 1; return *this; } - explicit operator bool() { - return sqlite3_column_count(_binder->_stmt.get()) >= next_index; - } - template - operator Type() { - Type value; + template + operator std::tuple() { + std::tuple value; *this >> value; return value; } + explicit operator bool() { + return sqlite3_column_count(_binder->_stmt.get()) >= next_index; + } private: database_binder *_binder; int next_index = 0; @@ -342,7 +348,6 @@ namespace sqlite { _binder = nullptr; break; default: - _binder = nullptr; exceptions::throw_sqlite_error(result, _binder->sql()); } return *this; From 5bbe246ae25512f7d7bd6d85ff602bb39dc2f1ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20Kr=C3=BCger?= Date: Wed, 24 May 2017 14:49:31 +0200 Subject: [PATCH 04/11] Implement all executions with iterators --- hdr/sqlite_modern_cpp.h | 191 +++++++++--------- .../utility/function_traits.h | 3 +- 2 files changed, 101 insertions(+), 93 deletions(-) diff --git a/hdr/sqlite_modern_cpp.h b/hdr/sqlite_modern_cpp.h index ca89125b..ee116555 100644 --- a/hdr/sqlite_modern_cpp.h +++ b/hdr/sqlite_modern_cpp.h @@ -95,16 +95,7 @@ namespace sqlite { _stmt(std::move(other._stmt)), _inx(other._inx), execution_started(other.execution_started) { } - void execute() { - _start_execute(); - int hresult; - - while((hresult = sqlite3_step(_stmt.get())) == SQLITE_ROW) {} - - if(hresult != SQLITE_DONE) { - errors::throw_sqlite_error(hresult, sql()); - } - } + void execute(); std::string sql() { #if SQLITE_VERSION_NUMBER >= 3014000 @@ -148,15 +139,6 @@ namespace sqlite { } return ++_inx; } - void _start_execute() { - _next_index(); - _inx = 0; - used(true); - } - - void _extract(std::function call_back); - - void _extract_single_value(std::function call_back); #ifdef _MSC_VER sqlite3_stmt* _prepare(const std::u16string& sql) { @@ -179,31 +161,6 @@ namespace sqlite { return tmp; } - template - struct is_sqlite_value : public std::integral_constant< - bool, - std::is_floating_point::value - || std::is_integral::value - || std::is_same::value - || std::is_same::value - || std::is_same::value - > { }; - template - struct is_sqlite_value< std::vector > : public std::integral_constant< - bool, - std::is_floating_point::value - || std::is_integral::value - || std::is_same::value - > { }; -#ifdef MODERN_SQLITE_STD_VARIANT_SUPPORT - template - struct is_sqlite_value< std::variant > : public std::integral_constant< - bool, - true - > { }; -#endif - - /* for vector support */ template friend database_binder& operator <<(database_binder& db, const std::vector& val); template friend void get_col_from_db(database_binder& db, int inx, std::vector& val); @@ -263,43 +220,56 @@ namespace sqlite { } } - template - typename std::enable_if::value, void>::type operator>>( - Result& value) { - this->_extract_single_value([&value, this] { - get_col_from_db(*this, 0, value); - }); - } - - template - void operator>>(std::tuple&& values) { - this->_extract_single_value([&values, this] { - tuple_iterate>::iterate(values, *this); - }); - } - - template - typename std::enable_if::value, void>::type operator>>( - Function&& func) { - typedef utility::function_traits traits; - - this->_extract([&func, this]() { - binder::run(*this, func); - }); - } friend class row_iterator; }; + namespace detail { + template + struct is_sqlite_value : public std::integral_constant< + bool, + std::is_floating_point::value + || std::is_integral::value + || std::is_same::value + || std::is_same::value + || std::is_same::value + > { }; + template + struct is_sqlite_value< std::vector > : public std::integral_constant< + bool, + std::is_floating_point::value + || std::is_integral::value + || std::is_same::value + > { }; + template + struct is_sqlite_value< std::unique_ptr > : public is_sqlite_value {}; +#ifdef MODERN_SQLITE_STD_VARIANT_SUPPORT + template + struct is_sqlite_value< std::variant > : public std::integral_constant< + bool, + true + > { }; +#endif +#ifdef MODERN_SQLITE_STD_OPTIONAL_SUPPORT + template + struct is_sqlite_value< std::optional > : public is_sqlite_value {}; +#endif + +#ifdef _MODERN_SQLITE_BOOST_OPTIONAL_SUPPORT + template + struct is_sqlite_value< boost::optional > : public is_sqlite_value {}; +#endif + } + class row_iterator { public: class value_type { public: value_type(database_binder *_binder): _binder(_binder) {}; template - typename std::enable_if::value, value_type &>::type operator >>(T &result) { + typename std::enable_if::value, value_type &>::type operator >>(T &result) { get_col_from_db(*_binder, next_index++, result); return *this; } - template::value, value_type &>::type> + template::value, value_type &>::type> operator T() { T result; *this >> result; @@ -313,6 +283,10 @@ namespace sqlite { return *this; } template + value_type &operator >>(std::tuple&& values) { + return *this >> values; + } + template operator std::tuple() { std::tuple value; *this >> value; @@ -332,7 +306,9 @@ namespace sqlite { row_iterator() = default; explicit row_iterator(database_binder &binder): _binder(&binder) { - _binder->_start_execute(); + _binder->_next_index(); + _binder->_inx = 0; + _binder->used(true); ++*this; } @@ -342,7 +318,6 @@ namespace sqlite { switch(int result = sqlite3_step(_binder->_stmt.get())) { case SQLITE_ROW: value = {_binder}; - /* tuple_iterate::iterate(_value, *_binder); */ break; case SQLITE_DONE: _binder = nullptr; @@ -374,20 +349,53 @@ namespace sqlite { inline row_iterator database_binder::end() { return row_iterator(); } - void database_binder::_extract(std::function call_back) { - for(auto &&row[[maybe_unused]] : *this) - call_back(); + + namespace detail { + template + void _extract_single_value(database_binder &binder, Callback call_back) { + auto iter = binder.begin(); + if(iter == binder.end()) + throw errors::no_rows("no rows to extract: exactly 1 row expected", binder.sql(), SQLITE_DONE); + + call_back(*iter); + + if(++iter != binder.end()) + throw errors::more_rows("not all rows extracted", binder.sql(), SQLITE_ROW); + } + } + void database_binder::execute() { + for(auto &&row : *this) + (void)row; + } + namespace detail { + template using void_t = void; + template + struct sqlite_direct_result : std::false_type {}; + template + struct sqlite_direct_result< + T, + void_t().operator>>(std::declval()))> + > : std::true_type {}; + } + template + inline typename std::enable_if::value>::type operator>>(database_binder &binder, Result&& value) { + detail::_extract_single_value(binder, [&value] (row_iterator::value_type &row) { + row >> std::forward(value); + }); } - void database_binder::_extract_single_value(std::function call_back) { - auto iter = begin(); - if(iter == end()) - throw errors::no_rows("no rows to extract: exactly 1 row expected", sql(), SQLITE_DONE); + template + inline typename std::enable_if::value>::type operator>>(database_binder &db_binder, Function&& func) { + using traits = utility::function_traits; - call_back(); + for(auto &&row : db_binder) { + binder::run(row, func); + } + } - if(++iter != end()) - throw errors::more_rows("not all rows extracted", sql(), SQLITE_ROW); + template + inline decltype(auto) operator>>(database_binder &&binder, Result&& value) { + return binder >> std::forward(value); } namespace sql_function_binder { @@ -592,14 +600,13 @@ namespace sqlite { std::size_t Boundary = Count > static typename std::enable_if<(sizeof...(Values) < Boundary), void>::type run( - database_binder& db, - Function&& function, - Values&&... values + row_iterator::value_type& row, + Function&& function, + Values&&... values ) { - typename std::remove_cv>::type>::type value{}; - get_col_from_db(db, sizeof...(Values), value); - - run(db, function, std::forward(values)..., std::move(value)); + typename std::decay>::type value; + row >> value; + run(row, function, std::forward(values)..., std::move(value)); } template< @@ -608,9 +615,9 @@ namespace sqlite { std::size_t Boundary = Count > static typename std::enable_if<(sizeof...(Values) == Boundary), void>::type run( - database_binder&, - Function&& function, - Values&&... values + row_iterator::value_type&, + Function&& function, + Values&&... values ) { function(std::move(values)...); } diff --git a/hdr/sqlite_modern_cpp/utility/function_traits.h b/hdr/sqlite_modern_cpp/utility/function_traits.h index cd8fab09..f629aa09 100644 --- a/hdr/sqlite_modern_cpp/utility/function_traits.h +++ b/hdr/sqlite_modern_cpp/utility/function_traits.h @@ -42,10 +42,11 @@ namespace sqlite { > { typedef ReturnType result_type; + using argument_tuple = std::tuple; template using argument = typename std::tuple_element< Index, - std::tuple + argument_tuple >::type; static const std::size_t arity = sizeof...(Arguments); From 30f945535a5a1ad291dc50ba9a7e232c2e2baa62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20Kr=C3=BCger?= Date: Mon, 24 Jul 2017 19:49:55 +0200 Subject: [PATCH 05/11] Less implicit conversations --- hdr/sqlite_modern_cpp.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/hdr/sqlite_modern_cpp.h b/hdr/sqlite_modern_cpp.h index ee116555..c4c19c6f 100644 --- a/hdr/sqlite_modern_cpp.h +++ b/hdr/sqlite_modern_cpp.h @@ -269,12 +269,6 @@ namespace sqlite { get_col_from_db(*_binder, next_index++, result); return *this; } - template::value, value_type &>::type> - operator T() { - T result; - *this >> result; - return result; - } template value_type &operator >>(std::tuple& values) { assert(!next_index); From 4b765b1634e4f88673c103b76fb3b10ed203e7c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20Kr=C3=BCger?= Date: Mon, 24 Jul 2017 20:13:46 +0200 Subject: [PATCH 06/11] Remove trailing whitespace --- tests/readme_example.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/readme_example.cc b/tests/readme_example.cc index 851587a9..00523341 100644 --- a/tests/readme_example.cc +++ b/tests/readme_example.cc @@ -45,7 +45,7 @@ int main() { db << "select age,name,weight from user where age > ? ;" << 21 >> [&](int _age, string _name, double _weight) { - if(_age != age || _name != name) + if(_age != age || _name != name) exit(EXIT_FAILURE); cout << _age << ' ' << _name << ' ' << _weight << endl; }; @@ -54,13 +54,13 @@ int main() { string _name; double _weight; row >> _age >> _name >> _weight; - if(_age != age || _name != name) + if(_age != age || _name != name) exit(EXIT_FAILURE); cout << _age << ' ' << _name << ' ' << _weight << endl; } for(std::tuple row : db << "select age,name,weight from user where age > ? ;" << 21) { - if(std::get(row) != age || std::get(row) != name) + if(std::get(row) != age || std::get(row) != name) exit(EXIT_FAILURE); cout << std::get(row) << ' ' << std::get(row) << ' ' << std::get(row) << endl; } From e7614523ff7144337739465b6cbaa76389952ec4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20Kr=C3=BCger?= Date: Mon, 24 Jul 2017 22:24:21 +0200 Subject: [PATCH 07/11] Implement tuple extraction via operator>> --- hdr/sqlite_modern_cpp.h | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/hdr/sqlite_modern_cpp.h b/hdr/sqlite_modern_cpp.h index c4c19c6f..6ed747e5 100644 --- a/hdr/sqlite_modern_cpp.h +++ b/hdr/sqlite_modern_cpp.h @@ -70,17 +70,6 @@ namespace sqlite { typedef std::shared_ptr connection_type; - template::value == Element)> struct tuple_iterate { - static void iterate(Tuple& t, database_binder& db) { - get_col_from_db(db, Element, std::get(t)); - tuple_iterate::iterate(t, db); - } - }; - - template struct tuple_iterate { - static void iterate(Tuple&, database_binder&) {} - }; - class row_iterator; class database_binder { @@ -270,12 +259,7 @@ namespace sqlite { return *this; } template - value_type &operator >>(std::tuple& values) { - assert(!next_index); - tuple_iterate>::iterate(values, *_binder); - next_index = sizeof...(Types) + 1; - return *this; - } + value_type &operator >>(std::tuple& values); template value_type &operator >>(std::tuple&& values) { return *this >> values; @@ -336,6 +320,27 @@ namespace sqlite { mutable value_type value{_binder}; // mutable, because `changing` the value is just reading it }; + namespace detail { + template::value == Element)> struct tuple_iterate { + static void iterate(Tuple& t, row_iterator::value_type& row) { + row >> std::get(t); + tuple_iterate::iterate(t, row); + } + }; + + template struct tuple_iterate { + static void iterate(Tuple&, row_iterator::value_type&) {} + }; + } + + template + row_iterator::value_type &row_iterator::value_type::operator >>(std::tuple& values) { + assert(!next_index); + detail::tuple_iterate>::iterate(values, *this); + next_index = sizeof...(Types) + 1; + return *this; + } + inline row_iterator database_binder::begin() { return row_iterator(*this); } From fde544f1449600dbc8a78f84190d8fd7dec73d5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20Kr=C3=BCger?= Date: Sun, 21 Jan 2018 21:01:06 +0100 Subject: [PATCH 08/11] Added example to README --- README.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f56869c4..c99fd27d 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ int main() { cout << "The new record got assigned id " << db.last_insert_rowid() << endl; - // slects from user table on a condition ( age > 18 ) and executes + // selects from user table on a condition ( age > 18 ) and executes // the lambda for each row returned . db << "select age,name,weight from user where age > ? ;" << 18 @@ -56,6 +56,18 @@ int main() { cout << age << ' ' << name << ' ' << weight << endl; }; + // a for loop can be used too: + // with named variables + for(auto &&row : db << "select age,name,weight from user where age > ? ;" << 18) { + int age; string name; double weight; + row >> age >> name >> weight; + cout << age << ' ' << name << ' ' << weight << endl; + } + // or with a tuple + for(tuple row : db << "select age,name,weight from user where age > ? ;" << 18) { + cout << get<0>(row) << ' ' << get<1>(row) << ' ' << get<2>(row) << endl; + } + // selects the count(*) from user table // note that you can extract a single culumn single row result only to : int,long,long,float,double,string,u16string int count = 0; From 8bc7d2576360e01c11ed03010a1e7c2f29a9da9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20Kr=C3=BCger?= Date: Sun, 21 Jan 2018 22:09:19 +0100 Subject: [PATCH 09/11] Fix bug with experimental optional --- hdr/sqlite_modern_cpp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hdr/sqlite_modern_cpp.h b/hdr/sqlite_modern_cpp.h index 6ed747e5..1f67f132 100644 --- a/hdr/sqlite_modern_cpp.h +++ b/hdr/sqlite_modern_cpp.h @@ -239,7 +239,7 @@ namespace sqlite { #endif #ifdef MODERN_SQLITE_STD_OPTIONAL_SUPPORT template - struct is_sqlite_value< std::optional > : public is_sqlite_value {}; + struct is_sqlite_value< optional > : public is_sqlite_value {}; #endif #ifdef _MODERN_SQLITE_BOOST_OPTIONAL_SUPPORT From 73b062d2129c7e640e62e4fce60c81cc5196105d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20Kr=C3=BCger?= Date: Wed, 24 Jan 2018 09:27:54 +0100 Subject: [PATCH 10/11] Drop declaration of missing operator --- hdr/sqlite_modern_cpp.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/hdr/sqlite_modern_cpp.h b/hdr/sqlite_modern_cpp.h index 1f67f132..fba6af1b 100644 --- a/hdr/sqlite_modern_cpp.h +++ b/hdr/sqlite_modern_cpp.h @@ -306,8 +306,6 @@ namespace sqlite { return *this; } - // Not well-defined - row_iterator operator++(int); friend inline bool operator ==(const row_iterator &a, const row_iterator &b) { return a._binder == b._binder; } From 65544ca206cd24cdd92ca376fb77ec4d06b01e83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20Kr=C3=BCger?= Date: Mon, 5 Feb 2018 19:09:55 +0100 Subject: [PATCH 11/11] Make execute inline --- hdr/sqlite_modern_cpp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hdr/sqlite_modern_cpp.h b/hdr/sqlite_modern_cpp.h index fba6af1b..a3ff93d9 100644 --- a/hdr/sqlite_modern_cpp.h +++ b/hdr/sqlite_modern_cpp.h @@ -360,7 +360,7 @@ namespace sqlite { throw errors::more_rows("not all rows extracted", binder.sql(), SQLITE_ROW); } } - void database_binder::execute() { + inline void database_binder::execute() { for(auto &&row : *this) (void)row; }