initial submission of variadic template for bind

tested with
CXXFLAGS="-std=c++14" cmake
with gcc 5.3.1.
This commit is contained in:
Paul Dreik 2016-06-04 22:06:38 +02:00
parent bf61578f59
commit 3022d50b38
3 changed files with 114 additions and 1 deletions

View File

@ -1935,7 +1935,7 @@ INCLUDE_FILE_PATTERNS =
# recursively expanded use the := operator instead of the = operator. # recursively expanded use the := operator instead of the = operator.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
PREDEFINED = PREDEFINED = __cplusplus=201402L
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
# tag can be used to specify a list of macro names that should be expanded. The # tag can be used to specify a list of macro names that should be expanded. The

View File

@ -16,6 +16,8 @@
#include <string> #include <string>
#include <SQLiteCpp/SQLiteCpp.h> #include <SQLiteCpp/SQLiteCpp.h>
#include <SQLiteCpp/VariadicBind.h>
#ifdef SQLITECPP_ENABLE_ASSERT_HANDLER #ifdef SQLITECPP_ENABLE_ASSERT_HANDLER
namespace SQLite namespace SQLite
@ -80,6 +82,34 @@ private:
SQLite::Statement mQuery; ///< Database prepared SQL query SQLite::Statement mQuery; ///< Database prepared SQL query
}; };
void demonstrateVariadicBind() {
#if ( __cplusplus>= 201402L) || ( defined(_MSC_VER) && (_MSC_VER >= 1900) )
// Open a database file in create/write mode
SQLite::Database db(":memory:", SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
db.exec("DROP TABLE IF EXISTS test");
db.exec("CREATE TABLE test (id INTEGER PRIMARY KEY, value TEXT)");
{
SQLite::Statement query(db, "INSERT INTO test VALUES (?, ?)");
SQLite::bind(query, 42, "fortytwo");
// Execute the one-step query to insert the blob
int nb = query.exec();
std::cout << "INSERT INTO test VALUES (NULL, ?)\", returned " << nb
<< std::endl;
}
SQLite::Statement query(db, "SELECT * FROM test");
std::cout << "SELECT * FROM test :\n";
if (query.executeStep()) {
std::cout << query.getColumn(0).getInt() << "\t\""
<< query.getColumn(1).getText() << "\"\n";
}
#else
throw std::runtime_error("demonstrateVariadicBind(): sorry, no c++14 support in this build.");
#endif
}
int main () int main ()
{ {
@ -422,6 +452,15 @@ int main ()
} }
remove("out.png"); remove("out.png");
//example with variadic bind (requires c++14)
try {
std::cout<<"cplusplus version is "<<__cplusplus<<'\n';
demonstrateVariadicBind();
} catch (std::exception& e) {
std::cout << "SQLite exception: " << e.what() << std::endl;
return EXIT_FAILURE; // unexpected error : exit the example program
}
std::cout << "everything ok, quitting\n"; std::cout << "everything ok, quitting\n";
return EXIT_SUCCESS; return EXIT_SUCCESS;

View File

@ -0,0 +1,74 @@
/**
* @file VariadicBind.h
* @ingroup SQLiteCpp
* @brief Convenience function for Statement::bind(...)
*
* Copyright (c) 2016 Paul Dreik (github@pauldreik.se)
*
* Distributed under the MIT License (MIT) (See accompanying file LICENSE.txt
* or copy at http://opensource.org/licenses/MIT)
*/
#pragma once
#include <SQLiteCpp/Statement.h>
namespace SQLite
{
//this requires c++14. seems like visual studio 2015 should work (yet untested).
#if ( __cplusplus>= 201402L) || ( defined(_MSC_VER) && (_MSC_VER >= 1900) )
/// @cond
#include <utility>
#include <initializer_list>
/// implementation detail for variadic bind.
namespace detail {
template<class F,class ...Args, std::size_t ... I>
inline void invoke_with_index(F&& f, std::integer_sequence<std::size_t, I...>,
const Args& ...args) {
std::initializer_list<int> { (f(I+1,args),0)... };
}
/// implementation detail for variadic bind.
template<class F,class ...Args>
inline void invoke_with_index(F&&f, const Args& ... args) {
invoke_with_index(std::forward<F>(f),std::index_sequence_for<Args...>(), args...);
}
} //namespace detail
/// @endcond
/**
* \brief Convenience function for calling Statement::bind(...) once for each argument given.
*
* This takes care of incrementing the index between each calls to bind.
*
* This feature requires a c++14 capable compiler.
*
* \code{.cpp}
* SQLite::Statement stm("SELECT * FROM MyTable WHERE colA>? && colB=? && colC<?");
* bind(stm,a,b,c);
* //...is equivalent to
* stm.bind(1,a);
* stm.bind(2,b);
* stm.bind(3,c);
* \endcode
* @param s statement
* @param args one or more args to bind.
*/
template<class ...Args>
void bind(SQLite::Statement& s,const Args& ... args) {
static_assert(sizeof...(args)>0,"please invoke bind with one or more args");
auto f=[&s](std::size_t index, const auto& value) {
s.bind(index,value);
};
detail::invoke_with_index(f, args...);
}
#else
//not supported in older c++. provide a fallback?
#endif // c++14
} // namespace SQLite