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&lt;T1, ...&gt;</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

Reply via email to