Am 20.10.2010 19:02, schrieb Mateusz Loskot:
On 20/10/10 17:08, Henning Basold wrote:
Hi,
I've attached a patch which enables SOCI to supporte all Boost.Fusion
sequence types and not just fusion::vector. It is a relativ simple
patch. But it needs a small change (not breaking) in the
type_conversion interface. Maybe this can be worked around if needed.
I would like to see this integrated into SOCI because it makes
adaption of UDT more convenient and also enables adaption of types
like std::pair just by including the appropriate Fusion headers.
Hi Henning,
First of all, thank you very much for the patch.
Did you generated it using git format-patch utility?
I'm having problems with applying it, it looks suspicious to me.
Best regards,
Hi,
sorry for multiple postings. But I thought there should be a test case
and some documentation about it. So I amended this to the patch (see
attachment). I don't know how you write the documentation, so I just
hacked it into the HTML document.
The integration of arbitrary fusion sequences works by using SFINAE (the
new parameter to type_conversion). A specialization of type_conversion
is then enabled iff the parameter T models a fusion sequence. Then this
specialization just passes the parameter through to a conversion struct
which uses the correct number of entries in the passed sequence. The
same technique is used within Boost.Spirit.
Hope that is clear.
Best regards
Henning
>From defd864af4d43a8c2bfa73e5853b0b36af0184cb Mon Sep 17 00:00:00 2001
From: Henning Basold <[email protected]>
Date: Wed, 20 Oct 2010 21:21:55 +0200
Subject: [PATCH] Support for arbitrary fusion sequences
---
doc/boost.html | 5 +-
src/core/boost-fusion.h | 125 ++++++++++++++++++++++---------------
src/core/test/common-tests.h | 53 ++++++++++++++++
src/core/type-conversion-traits.h | 2 +-
4 files changed, 132 insertions(+), 53 deletions(-)
diff --git a/doc/boost.html b/doc/boost.html
index dc441e8..b460239 100644
--- a/doc/boost.html
+++ b/doc/boost.html
@@ -69,9 +69,10 @@ else
}
</pre>
-<h4>boost::fusion::vector<T1, ...></h4>
+<h4>Boost.Fusion</h4>
-<p>The <code>boost::fusion::vector</code> types are supported in the same way as tuples.</p>
+<p>Types that model a Boost.Fusion <code>Random Access Sequence</code> are supported in the same way as tuples. That means one can use
+<code>boost::fusion::vector</code>, <code>BOOST_FUSION_ADAPT_STRUCT</code> etc. with SOCI.</p>
<h4>boost::gregorian::date</h4>
diff --git a/src/core/boost-fusion.h b/src/core/boost-fusion.h
index 01a667b..9e401a4 100644
--- a/src/core/boost-fusion.h
+++ b/src/core/boost-fusion.h
@@ -13,24 +13,31 @@
// boost
#include <boost/fusion/container/vector.hpp>
#include <boost/fusion/sequence/intrinsic/at.hpp>
+#include <boost/fusion/sequence/intrinsic/size.hpp>
#include <boost/fusion/include/at.hpp>
+#include <boost/fusion/support/is_sequence.hpp>
+#include <boost/utility/enable_if.hpp>
namespace soci
{
+namespace detail
+{
+template <typename Seq, int size>
+struct type_conversion;
-template <typename T0>
-struct type_conversion<boost::fusion::vector<T0> >
+template <typename Seq>
+struct type_conversion<Seq, 1>
{
typedef values base_type;
static void from_base(base_type const & in, indicator ind,
- boost::fusion::vector<T0> & out)
+ Seq & out)
{
in
>> boost::fusion::at_c<0>(out);
}
- static void to_base(boost::fusion::vector<T0> & in,
+ static void to_base(Seq & in,
base_type & out, indicator & ind)
{
out
@@ -38,20 +45,20 @@ struct type_conversion<boost::fusion::vector<T0> >
}
};
-template <typename T0, typename T1>
-struct type_conversion<boost::fusion::vector<T0, T1> >
+template <typename Seq>
+struct type_conversion<Seq, 2>
{
typedef values base_type;
static void from_base(base_type const & in, indicator ind,
- boost::fusion::vector<T0, T1> & out)
+ Seq & out)
{
in
>> boost::fusion::at_c<0>(out)
>> boost::fusion::at_c<1>(out);
}
- static void to_base(boost::fusion::vector<T0, T1> & in,
+ static void to_base(Seq & in,
base_type & out, indicator & ind)
{
out
@@ -60,13 +67,13 @@ struct type_conversion<boost::fusion::vector<T0, T1> >
}
};
-template <typename T0, typename T1, typename T2>
-struct type_conversion<boost::fusion::vector<T0, T1, T2> >
+template <typename Seq>
+struct type_conversion<Seq, 3>
{
typedef values base_type;
static void from_base(base_type const & in, indicator ind,
- boost::fusion::vector<T0, T1, T2> & out)
+ Seq & out)
{
in
>> boost::fusion::at_c<0>(out)
@@ -74,7 +81,7 @@ struct type_conversion<boost::fusion::vector<T0, T1, T2> >
>> boost::fusion::at_c<2>(out);
}
- static void to_base(boost::fusion::vector<T0, T1, T2> & in,
+ static void to_base(Seq & in,
base_type & out, indicator & ind)
{
out
@@ -84,13 +91,13 @@ struct type_conversion<boost::fusion::vector<T0, T1, T2> >
}
};
-template <typename T0, typename T1, typename T2, typename T3>
-struct type_conversion<boost::fusion::vector<T0, T1, T2, T3> >
+template <typename Seq>
+struct type_conversion<Seq, 4>
{
typedef values base_type;
static void from_base(base_type const & in, indicator ind,
- boost::fusion::vector<T0, T1, T2, T3> & out)
+ Seq & out)
{
in
>> boost::fusion::at_c<0>(out)
@@ -99,7 +106,7 @@ struct type_conversion<boost::fusion::vector<T0, T1, T2, T3> >
>> boost::fusion::at_c<3>(out);
}
- static void to_base(boost::fusion::vector<T0, T1, T2, T3> & in,
+ static void to_base(Seq & in,
base_type & out, indicator & ind)
{
out
@@ -110,13 +117,13 @@ struct type_conversion<boost::fusion::vector<T0, T1, T2, T3> >
}
};
-template <typename T0, typename T1, typename T2, typename T3, typename T4>
-struct type_conversion<boost::fusion::vector<T0, T1, T2, T3, T4> >
+template <typename Seq>
+struct type_conversion<Seq, 5>
{
typedef values base_type;
static void from_base(base_type const & in, indicator ind,
- boost::fusion::vector<T0, T1, T2, T3, T4> & out)
+ Seq & out)
{
in
>> boost::fusion::at_c<0>(out)
@@ -126,7 +133,7 @@ struct type_conversion<boost::fusion::vector<T0, T1, T2, T3, T4> >
>> boost::fusion::at_c<4>(out);
}
- static void to_base(boost::fusion::vector<T0, T1, T2, T3, T4> & in,
+ static void to_base(Seq & in,
base_type & out, indicator & ind)
{
out
@@ -138,14 +145,13 @@ struct type_conversion<boost::fusion::vector<T0, T1, T2, T3, T4> >
}
};
-template <typename T0, typename T1, typename T2, typename T3, typename T4,
- typename T5>
-struct type_conversion<boost::fusion::vector<T0, T1, T2, T3, T4, T5> >
+template <typename Seq>
+struct type_conversion<Seq, 6>
{
typedef values base_type;
static void from_base(base_type const & in, indicator ind,
- boost::fusion::vector<T0, T1, T2, T3, T4, T5> & out)
+ Seq & out)
{
in
>> boost::fusion::at_c<0>(out)
@@ -156,7 +162,7 @@ struct type_conversion<boost::fusion::vector<T0, T1, T2, T3, T4, T5> >
>> boost::fusion::at_c<5>(out);
}
- static void to_base(boost::fusion::vector<T0, T1, T2, T3, T4, T5> & in,
+ static void to_base(Seq & in,
base_type & out, indicator & ind)
{
out
@@ -169,14 +175,13 @@ struct type_conversion<boost::fusion::vector<T0, T1, T2, T3, T4, T5> >
}
};
-template <typename T0, typename T1, typename T2, typename T3, typename T4,
- typename T5, typename T6>
-struct type_conversion<boost::fusion::vector<T0, T1, T2, T3, T4, T5, T6> >
+template <typename Seq>
+struct type_conversion<Seq, 7>
{
typedef values base_type;
static void from_base(base_type const & in, indicator ind,
- boost::fusion::vector<T0, T1, T2, T3, T4, T5, T6> & out)
+ Seq & out)
{
in
>> boost::fusion::at_c<0>(out)
@@ -188,7 +193,7 @@ struct type_conversion<boost::fusion::vector<T0, T1, T2, T3, T4, T5, T6> >
>> boost::fusion::at_c<6>(out);
}
- static void to_base(boost::fusion::vector<T0, T1, T2, T3, T4, T5, T6> & in,
+ static void to_base(Seq & in,
base_type & out, indicator & ind)
{
out
@@ -202,14 +207,13 @@ struct type_conversion<boost::fusion::vector<T0, T1, T2, T3, T4, T5, T6> >
}
};
-template <typename T0, typename T1, typename T2, typename T3, typename T4,
- typename T5, typename T6, typename T7>
-struct type_conversion<boost::fusion::vector<T0, T1, T2, T3, T4, T5, T6, T7> >
+template <typename Seq>
+struct type_conversion<Seq, 8>
{
typedef values base_type;
static void from_base(base_type const & in, indicator ind,
- boost::fusion::vector<T0, T1, T2, T3, T4, T5, T6, T7> & out)
+ Seq & out)
{
in
>> boost::fusion::at_c<0>(out)
@@ -222,8 +226,7 @@ struct type_conversion<boost::fusion::vector<T0, T1, T2, T3, T4, T5, T6, T7> >
>> boost::fusion::at_c<7>(out);
}
- static void to_base(
- boost::fusion::vector<T0, T1, T2, T3, T4, T5, T6, T7> & in,
+ static void to_base(Seq & in,
base_type & out, indicator & ind)
{
out
@@ -238,15 +241,13 @@ struct type_conversion<boost::fusion::vector<T0, T1, T2, T3, T4, T5, T6, T7> >
}
};
-template <typename T0, typename T1, typename T2, typename T3, typename T4,
- typename T5, typename T6, typename T7, typename T8>
-struct type_conversion<
- boost::fusion::vector<T0, T1, T2, T3, T4, T5, T6, T7, T8> >
+template <typename Seq>
+struct type_conversion<Seq, 9>
{
typedef values base_type;
static void from_base(base_type const & in, indicator ind,
- boost::fusion::vector<T0, T1, T2, T3, T4, T5, T6, T7, T8> & out)
+ Seq & out)
{
in
>> boost::fusion::at_c<0>(out)
@@ -260,8 +261,7 @@ struct type_conversion<
>> boost::fusion::at_c<8>(out);
}
- static void to_base(
- boost::fusion::vector<T0, T1, T2, T3, T4, T5, T6, T7, T8> & in,
+ static void to_base(Seq & in,
base_type & out, indicator & ind)
{
out
@@ -277,15 +277,13 @@ struct type_conversion<
}
};
-template <typename T0, typename T1, typename T2, typename T3, typename T4,
- typename T5, typename T6, typename T7, typename T8, typename T9>
-struct type_conversion<
- boost::fusion::vector<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> >
+template <typename Seq>
+struct type_conversion<Seq, 10>
{
typedef values base_type;
static void from_base(base_type const & in, indicator ind,
- boost::fusion::vector<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> & out)
+ Seq & out)
{
in
>> boost::fusion::at_c<0>(out)
@@ -300,8 +298,7 @@ struct type_conversion<
>> boost::fusion::at_c<9>(out);
}
- static void to_base(
- boost::fusion::vector<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9> & in,
+ static void to_base(Seq & in,
base_type & out, indicator & ind)
{
out
@@ -318,6 +315,34 @@ struct type_conversion<
}
};
+} // namespace detail
+
+template <typename T>
+struct type_conversion<T,
+ typename boost::enable_if<
+ boost::fusion::traits::is_sequence<T>
+ >::type >
+{
+ typedef values base_type;
+
+private:
+ typedef typename boost::fusion::result_of::size<T>::type size;
+ typedef detail::type_conversion<T, size::value> converter;
+
+public:
+ static void from_base(base_type const & in, indicator ind,
+ T& out)
+ {
+ converter::from_base( in, ind, out );
+ }
+
+ static void to_base(T& in,
+ base_type & out, indicator & ind)
+ {
+ converter::to_base( in, out, ind );
+ }
+};
+
} // namespace soci
#endif // SOCI_BOOST_FUSION_H_INCLUDED
diff --git a/src/core/test/common-tests.h b/src/core/test/common-tests.h
index e38d915..0873cd2 100644
--- a/src/core/test/common-tests.h
+++ b/src/core/test/common-tests.h
@@ -19,6 +19,7 @@
#include <boost-gregorian-date.h>
#if defined(BOOST_VERSION) && BOOST_VERSION >= 103500
#include <boost-fusion.h>
+#include <boost/fusion/include/adapt_struct.hpp>
#endif // BOOST_VERSION
#endif // HAVE_BOOST
@@ -151,6 +152,32 @@ template<> struct type_conversion<PhonebookEntry3>
} // namespace soci
+// test cooperation with BOOST_FUSION_ADAPT_STRUCT
+#ifdef HAVE_BOOST
+#if defined(BOOST_VERSION) && BOOST_VERSION >= 103500
+
+namespace soci { namespace tests {
+struct FusionAdaptTestStruct {
+ FusionAdaptTestStruct(){}
+
+ FusionAdaptTestStruct(double m1_, boost::optional<int> const& m2_, std::string m3_)
+ : m1(m1_), m2(m2_), m3(m3_) {}
+
+ double m1;
+ boost::optional<int> m2;
+ std::string m3;
+};
+}}
+
+BOOST_FUSION_ADAPT_STRUCT(
+ soci::tests::FusionAdaptTestStruct,
+ (double, m1)
+ (boost::optional<int>, m2)
+ (std::string, m3))
+
+#endif
+#endif // HAVE_BOOST
+
namespace soci
{
namespace tests
@@ -3396,6 +3423,32 @@ void test29()
++pos;
assert(pos == rs.end());
+
+ sql << "delete from soci_test";
+ }
+
+ {
+ // struct adaption
+
+ // use:
+ FusionAdaptTestStruct t1(3.5, boost::optional<int>(7), "Joe Hacker");
+ assert(boost::fusion::at_c<0>(t1) == 3.5);
+ assert(boost::fusion::at_c<1>(t1).is_initialized());
+ assert(boost::fusion::at_c<1>(t1).get() == 7);
+ assert(boost::fusion::at_c<2>(t1) == "Joe Hacker");
+
+ sql << "insert into soci_test(num_float, num_int, name) values(:d, :i, :s)", use(t1);
+
+ // into:
+ FusionAdaptTestStruct t2;
+ sql << "select num_float, num_int, name from soci_test", into(t2);
+
+ assert(t2.m1 == 3.5);
+ assert(t2.m2.is_initialized());
+ assert(t2.m2 == 7);
+ assert(t2.m3 == "Joe Hacker");
+
+ sql << "delete from soci_test";
}
std::cout << "test 29 passed" << std::endl;
diff --git a/src/core/type-conversion-traits.h b/src/core/type-conversion-traits.h
index 5a539d2..8ebbb3b 100644
--- a/src/core/type-conversion-traits.h
+++ b/src/core/type-conversion-traits.h
@@ -15,7 +15,7 @@ namespace soci
// default traits class type_conversion, acts as pass through for row::get()
// when no actual conversion is needed.
-template <typename T>
+template <typename T, typename Enable = void>
struct type_conversion
{
typedef T base_type;
--
1.7.0.4
------------------------------------------------------------------------------
Nokia and AT&T present the 2010 Calling All Innovators-North America contest
Create new apps & games for the Nokia N8 for consumers in U.S. and Canada
$10 million total in prizes - $4M cash, 500 devices, nearly $6M in marketing
Develop with Nokia Qt SDK, Web Runtime, or Java and Publish to Ovi Store
http://p.sf.net/sfu/nokia-dev2dev
_______________________________________________
Soci-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/soci-users