Added support for std::tuple to Data/Typehandler.h.

This commit is contained in:
Friedrich Wilckens 2017-01-16 17:49:25 -08:00
parent 28de783c96
commit cc09e53b6a
3 changed files with 157 additions and 1 deletions

View File

@ -30,6 +30,9 @@
#include "Poco/SharedPtr.h"
#include <cstddef>
#if __cplusplus >= 201103L
#include <tuple>
#endif
namespace Poco {
namespace Data {
@ -2104,6 +2107,131 @@ private:
};
#if __cplusplus >= 201103L
template<size_t N>
struct TupleBind
/// Helper for specialization of type handler for std::tuple
{
template<typename... T>
static typename std::enable_if<N < sizeof...(T)>::type
bind(std::size_t& pos, const std::tuple<T...>& t, AbstractBinder::Ptr pBinder, AbstractBinder::Direction dir)
{
using Type = typename std::tuple_element<N, std::tuple<T...>>::type;
TypeHandler<Type>::bind(pos, std::get<N>(t), pBinder, dir);
pos += TypeHandler<Type>::size();
TupleBind<N+1>::bind(pos, t, pBinder, dir);
}
template<typename... T>
static typename std::enable_if<!(N < sizeof...(T))>::type
bind(std::size_t& pos, const std::tuple<T...>& t, AbstractBinder::Ptr pBinder, AbstractBinder::Direction dir)
{}
};
template<size_t N>
struct TupleSize
/// Helper for specialization of type handler for std::tuple
{
template<typename... T>
static typename std::enable_if<N < sizeof...(T)>::type
size(std::size_t& sz)
{
using Type = typename std::tuple_element<N, std::tuple<T...>>::type;
sz += TypeHandler<Type>::size();
TupleSize<N+1>::size(sz);
}
template<typename... T>
static typename std::enable_if<!(N < sizeof...(T))>::type
size(std::size_t& sz)
{}
};
template<size_t N>
struct TupleExtract
/// Helper for specialization of type handler for std::tuple
{
template<typename... T>
static typename std::enable_if<N < sizeof...(T)>::type
extract(std::size_t& pos, std::tuple<T...>& t, const std::tuple<T...>& defVal, AbstractExtractor::Ptr pExt)
{
using Type = typename std::tuple_element<N, std::tuple<T...>>::type;
TypeHandler<Type>::extract(pos, std::get<N>(t), std::get<N>(defVal), pExt);
pos += TypeHandler<Type>::size();
TupleExtract<N+1>::extract(pos, t, defVal, pExt);
}
template<typename... T>
static typename std::enable_if<!(N < sizeof...(T))>::type
extract(std::size_t& pos, std::tuple<T...>& t, const std::tuple<T...>& defVal, AbstractExtractor::Ptr pExt)
{}
};
template<size_t N>
struct TuplePrepare
/// Helper for specialization of type handler for std::tuple
{
template<typename... T>
static typename std::enable_if<N < sizeof...(T)>::type
prepare(std::size_t& pos, const std::tuple<T...>& t, AbstractPreparator::Ptr pPreparator)
{
using Type = typename std::tuple_element<N, std::tuple<T...>>::type;
TypeHandler<Type>::prepare(pos, std::get<N>(t), pPreparator);
pos += TypeHandler<Type>::size();
TuplePrepare<N+1>::prepare(pos, t, pPreparator);
}
template<typename... T>
static typename std::enable_if<!(N < sizeof...(T))>::type
prepare(std::size_t& pos, const std::tuple<T...>& t, AbstractPreparator::Ptr pPreparator)
{}
};
template <typename...T>
class TypeHandler<std::tuple<T...>>
/// Specialization of type handler for std::tuple
{
public:
static void bind(std::size_t pos, const std::tuple<T...> & t, AbstractBinder::Ptr pBinder, AbstractBinder::Direction dir)
{
poco_assert_dbg (!pBinder.isNull());
TupleBind<0>::bind(pos, t, pBinder, dir);
}
static std::size_t size()
{
std::size_t sz = 0;
TupleSize<0>::size(sz);
return sz;
}
static void extract(std::size_t pos, std::tuple<T...>& t, const std::tuple<T...>& defVal, AbstractExtractor::Ptr pExt)
{
poco_assert_dbg (!pExt.isNull());
TupleExtract<0>::extract(pos, t, defVal, pExt);
}
static void prepare(std::size_t pos, const std::tuple<T...> & t, AbstractPreparator::Ptr pPrepare)
{
poco_assert_dbg (!pPrepare.isNull());
TuplePrepare<0>::prepare(pos, t, pPrepare);
}
private:
TypeHandler();
~TypeHandler();
TypeHandler(const TypeHandler&);
TypeHandler& operator=(const TypeHandler&);
};
#endif // __cplusplus >= 201103L
} } // namespace Poco::Data

View File

@ -38,6 +38,10 @@
#include <iomanip>
#include <set>
#if __cplusplus >= 201103L
#include <tuple>
#endif
using namespace Poco::Data::Keywords;
@ -1400,6 +1404,22 @@ void DataTest::testExternalBindingAndExtraction()
}
#if __cplusplus >= 201103L
void DataTest::testStdTuple()
{
using Row = std::tuple<std::string, std::string, int>;
Session sess(SessionFactory::instance().create("test", "cs"));
Row person = std::make_tuple(std::string("Scott"), std::string("Washington, DC"), 42);
sess << "INSERT INTO Person(name, address, age) VALUES (?, ?, ?)", use(person), now;
std::vector<Row> rows;
sess << "SELECT name, address, age FROM Person", into(rows) , now;
}
#endif // __cplusplus >= 201103L
void DataTest::setUp()
{
}
@ -1430,7 +1450,11 @@ CppUnit::Test* DataTest::suite()
CppUnit_addTest(pSuite, DataTest, testSimpleRowFormatter);
CppUnit_addTest(pSuite, DataTest, testJSONRowFormatter);
CppUnit_addTest(pSuite, DataTest, testDateAndTime);
CppUnit_addTest(pSuite, DataTest, testExternalBindingAndExtraction);
CppUnit_addTest(pSuite, DataTest, testExternalBindingAndExtraction);
#if __cplusplus >= 201103L
CppUnit_addTest(pSuite, DataTest, testStdTuple);
#endif
return pSuite;
}

View File

@ -47,6 +47,10 @@ public:
void testDateAndTime();
void testExternalBindingAndExtraction();
#if __cplusplus >= 201103L
void testStdTuple();
#endif
void setUp();
void tearDown();