$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r70224 - in trunk/boost/spirit/home: karma/detail karma/directive karma/operator qi/detail support/utree
From: hartmut.kaiser_at_[hidden]
Date: 2011-03-20 14:23:50
Author: hkaiser
Date: 2011-03-20 14:23:49 EDT (Sun, 20 Mar 2011)
New Revision: 70224
URL: http://svn.boost.org/trac/boost/changeset/70224
Log:
Spirit: new container attribute handling for Karma, aligned with latest changes to Qi, minor tweaks to attribute handling in Qi, added comments, etc.
Text files modified: 
   trunk/boost/spirit/home/karma/detail/pass_container.hpp |   347 ++++++++++++++++++++++++++------------- 
   trunk/boost/spirit/home/karma/directive/repeat.hpp      |     2                                         
   trunk/boost/spirit/home/karma/operator/kleene.hpp       |     2                                         
   trunk/boost/spirit/home/karma/operator/list.hpp         |     2                                         
   trunk/boost/spirit/home/karma/operator/plus.hpp         |     2                                         
   trunk/boost/spirit/home/karma/operator/sequence.hpp     |     2                                         
   trunk/boost/spirit/home/qi/detail/pass_container.hpp    |    21 +-                                      
   trunk/boost/spirit/home/support/utree/utree_traits.hpp  |    76 +++++---                                
   8 files changed, 289 insertions(+), 165 deletions(-)
Modified: trunk/boost/spirit/home/karma/detail/pass_container.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/detail/pass_container.hpp	(original)
+++ trunk/boost/spirit/home/karma/detail/pass_container.hpp	2011-03-20 14:23:49 EDT (Sun, 20 Mar 2011)
@@ -24,70 +24,222 @@
 #include <boost/preprocessor/cat.hpp>
 #include <boost/preprocessor/repetition/repeat.hpp>
 #include <boost/range/iterator_range.hpp>
+#include <boost/fusion/include/deduce_sequence.hpp>
+
+#include <boost/mpl/print.hpp>
 
 namespace boost { namespace spirit { namespace karma { namespace detail
 {
-    // has_same_elements: utility to check if the LHS attribute
-    // is an STL container and that its value_type is convertible
-    // to the RHS.
-
-    template <typename RHS, typename LHSAttribute
-      , bool IsContainer = traits::is_container<LHSAttribute>::value
-      , bool IsSequence = fusion::traits::is_sequence<LHSAttribute>::value>
-    struct has_same_elements : mpl::false_ {};
-
-    template <typename RHS, typename LHSAttribute>
-    struct has_same_elements<RHS, LHSAttribute, true, false>
-      : mpl::or_<
-            is_convertible<RHS, typename LHSAttribute::value_type>
-          , traits::is_hold_any<typename LHSAttribute::value_type>
-        > {};
-
-    template <typename RHS, typename T>
-    struct has_same_elements<RHS, boost::optional<T>, false, false>
-      : has_same_elements<RHS, T> {};
-
-    template <typename RHS, typename T>
-    struct has_same_elements<RHS, boost::optional<T>, true, false>
-      : has_same_elements<RHS, T> {};
-
-    template <typename RHS, typename T>
-    struct has_same_elements<RHS, boost::optional<T>, false, true>
-      : has_same_elements<RHS, T> {};
-
-#define BOOST_SPIRIT_IS_CONVERTIBLE(z, N, data)                               \
-        has_same_elements<RHS, BOOST_PP_CAT(T, N)>::value ||                  \
-    /***/
-
-    // Note: variants are treated as containers if one of the held types is a
-    //       container (see support/container.hpp).
-    template <typename RHS, BOOST_VARIANT_ENUM_PARAMS(typename T)>
-    struct has_same_elements<
-            RHS, boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, true, false>
-      : mpl::bool_<BOOST_PP_REPEAT(BOOST_VARIANT_LIMIT_TYPES
-          , BOOST_SPIRIT_IS_CONVERTIBLE, _) false> {};
+    // Helper meta-function allowing to evaluate weak substitutability and
+    // negate the result if the predicate (Sequence) is not true
+    template <typename Sequence, typename Attribute, typename ValueType>
+    struct negate_weak_substitute_if_not
+      : mpl::if_<
+            Sequence
+          , typename traits::is_weak_substitute<Attribute, ValueType>::type
+          , typename mpl::not_<
+                traits::is_weak_substitute<Attribute, ValueType> 
+            >::type>
+    {};
+
+    // pass_through_container: utility to check decide whether a provided 
+    // container attribute needs to be passed through to the current component 
+    // or of we need to split the container by passing along instances of its
+    // value type
+
+    // if the expected attribute of the current component is neither a Fusion 
+    // sequence nor a container, we will pass through the provided container 
+    // only if its value type is not compatible with the component
+    template <typename Container, typename ValueType, typename Attribute
+      , typename Sequence, typename Enable = void>
+    struct pass_through_container_base
+      : negate_weak_substitute_if_not<Sequence, ValueType, Attribute>
+    {};
+
+    // Specialization for fusion sequences, in this case we check whether all
+    // the types in the sequence are convertible to the lhs attribute.
+    // 
+    // We return false if the rhs attribute itself is a fusion sequence, which
+    // is compatible with the LHS sequence (we want to pass through this 
+    // attribute without it being split apart).
+    template <typename Container, typename ValueType, typename Attribute
+      , typename Sequence = mpl::true_>
+    struct not_compatible_element
+      : mpl::and_<
+            negate_weak_substitute_if_not<Sequence, Container, Attribute>
+          , negate_weak_substitute_if_not<Sequence, ValueType, Attribute> >
+    {};
+
+    // If the value type of the container is not a Fusion sequence, we pass
+    // through the container if each of the elements of the Attribute 
+    // sequence is compatible with either the container or its value type.
+    template <typename Container, typename ValueType, typename Attribute
+      , typename Sequence
+      , bool IsSequence = fusion::traits::is_sequence<ValueType>::value>
+    struct pass_through_container_fusion_sequence
+    {
+        typedef typename mpl::find_if<
+            Attribute, not_compatible_element<Container, ValueType, mpl::_1>
+        >::type iter;
+        typedef typename mpl::end<Attribute>::type end;
 
-#undef BOOST_SPIRIT_IS_CONVERTIBLE
+        typedef typename is_same<iter, end>::type type;
+    };
 
-    // Specialization for fusion sequences, in this case we check whether the
-    // lhs attribute is convertible to the types in the sequence.
-    // We return false if the rhs attribute itself is a fusion sequence.
-    template <typename RHS, typename LHSAttribute>
-    struct has_same_elements<RHS, LHSAttribute, false, true>
+    // If both, the Attribute and the value type of the provided container
+    // are Fusion sequences, we pass the container only if the two 
+    // sequences are not compatible.
+    template <typename Container, typename ValueType, typename Attribute
+      , typename Sequence>
+    struct pass_through_container_fusion_sequence<
+            Container, ValueType, Attribute, Sequence, true>
     {
         typedef typename mpl::find_if<
-            LHSAttribute, mpl::not_<is_convertible<RHS, mpl::_1> >
+            Attribute
+          , not_compatible_element<Container, ValueType, mpl::_1, Sequence>
         >::type iter;
-        typedef typename mpl::end<LHSAttribute>::type end;
+        typedef typename mpl::end<Attribute>::type end;
 
         typedef typename is_same<iter, end>::type type;
     };
 
+    template <typename Container, typename ValueType, typename Attribute
+      , typename Sequence>
+    struct pass_through_container_base<Container, ValueType, Attribute
+          , Sequence
+          , typename enable_if<fusion::traits::is_sequence<Attribute> >::type>
+      : pass_through_container_fusion_sequence<
+            Container, ValueType, Attribute, Sequence>
+    {};
+
+    // Specialization for containers
+    //
+    // If the value type of the attribute of the current component is not
+    // a Fusion sequence, we have to pass through the provided container if 
+    // both are compatible.
+    template <typename Container, typename ValueType, typename Attribute
+      , typename Sequence, typename AttributeValueType
+      , bool IsSequence = fusion::traits::is_sequence<AttributeValueType>::value>
+    struct pass_through_container_container
+      : mpl::or_<
+            traits::is_weak_substitute<Container, Attribute> 
+          , traits::is_weak_substitute<Container, AttributeValueType> >
+    {};
+
+    // If the value type of the exposed container attribute is a Fusion
+    // sequence, we use the already existing logic for those.
+    template <typename Container, typename ValueType, typename Attribute
+      , typename Sequence, typename AttributeValueType>
+    struct pass_through_container_container<
+            Container, ValueType, Attribute, Sequence, AttributeValueType, true>
+      : pass_through_container_fusion_sequence<
+            Container, ValueType, AttributeValueType, Sequence>
+    {};
+
+    template <typename Container, typename ValueType, typename Attribute
+      , typename Sequence>
+    struct pass_through_container_base<Container, ValueType, Attribute
+          , Sequence
+          , typename enable_if<traits::is_container<Attribute> >::type>
+      : detail::pass_through_container_container<
+          Container, ValueType, Attribute, Sequence
+        , typename traits::container_value<Attribute>::type>
+    {};
+
+    // Specialization for exposed optional attributes
+    //
+    // If the type embedded in the exposed optional is not a Fusion 
+    // sequence we pass through the container attribute if it is compatible
+    // either to the optionals embedded type or to the containers value 
+    // type.
+    template <typename Container, typename ValueType, typename Attribute
+      , typename Sequence
+      , bool IsSequence = fusion::traits::is_sequence<Attribute>::value>
+    struct pass_through_container_optional
+      : mpl::or_<
+            traits::is_weak_substitute<Container, Attribute> 
+          , traits::is_weak_substitute<ValueType, Attribute> >
+    {};
+
+    // If the embedded type of the exposed optional attribute is a Fusion
+    // sequence, we use the already existing logic for those.
+    template <typename Container, typename ValueType, typename Attribute
+      , typename Sequence>
+    struct pass_through_container_optional<
+            Container, ValueType, Attribute, Sequence, true>
+      : pass_through_container_fusion_sequence<
+            Container, ValueType, Attribute, Sequence>
+    {};
+
+    ///////////////////////////////////////////////////////////////////////////
+    template <typename Container, typename ValueType, typename Attribute
+      , typename Sequence>
+    struct pass_through_container
+      : pass_through_container_base<Container, ValueType, Attribute, Sequence> 
+    {};
+
+    // Handle optional attributes
+    template <typename Container, typename ValueType, typename Attribute
+      , typename Sequence>
+    struct pass_through_container<
+            Container, ValueType, boost::optional<Attribute>, Sequence>
+      : pass_through_container_optional<
+            Container, ValueType, Attribute, Sequence> 
+    {};
+
+    // If both, the containers value type and the exposed attribute type are
+    // optionals we are allowed to pass through the the container only if the
+    // embedded types of those optionals are not compatible.
+    template <typename Container, typename ValueType, typename Attribute
+      , typename Sequence>
+    struct pass_through_container<
+            Container, boost::optional<ValueType>, boost::optional<Attribute>
+          , Sequence>
+      : mpl::not_<traits::is_weak_substitute<ValueType, Attribute> >
+    {};
+
+    // Specialization for exposed variant attributes
+    // 
+    // We pass through the container attribute if at least one of the embedded 
+    // types in the variant requires to pass through the attribute
+
+#define BOOST_SPIRIT_PASS_THROUGH_CONTAINER(z, N, _)                          \
+    pass_through_container<Container, ValueType,                              \
+        BOOST_PP_CAT(T, N), Sequence>::type::value ||                         \
+    /***/
+
+    template <typename Container, typename ValueType, typename Sequence
+      , BOOST_VARIANT_ENUM_PARAMS(typename T)>
+    struct pass_through_container<Container, ValueType
+          , boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Sequence>
+      : mpl::bool_<BOOST_PP_REPEAT(BOOST_VARIANT_LIMIT_TYPES
+          , BOOST_SPIRIT_PASS_THROUGH_CONTAINER, _) false>
+    {};
+
+#undef BOOST_SPIRIT_PASS_THROUGH_CONTAINER
+}}}}
+
+///////////////////////////////////////////////////////////////////////////////
+namespace boost { namespace spirit { namespace traits
+{
+    ///////////////////////////////////////////////////////////////////////////
+    // forwarding customization point for domain karma::domain
+    template <typename Container, typename ValueType, typename Attribute
+      , typename Sequence>
+    struct pass_through_container<
+            Container, ValueType, Attribute, Sequence, karma::domain>
+      : karma::detail::pass_through_container<
+            Container, ValueType, Attribute, Sequence>
+    {};
+}}}
+
+namespace boost { namespace spirit { namespace karma { namespace detail
+{
     ///////////////////////////////////////////////////////////////////////////
     // This function handles the case where the attribute (Attr) given
     // to the sequence is an STL container. This is a wrapper around F.
     // The function F does the actual generating.
-    template <typename F, typename Attr, typename Iterator, typename Strict>
+    template <typename F, typename Attr, typename Iterator, typename Sequence>
     struct pass_container
     {
         typedef typename F::context_type context_type;
@@ -109,7 +261,7 @@
         // this is for the case when the current element expects an attribute
         // which is taken from the next entry in the container
         template <typename Component>
-        bool dispatch_attribute_element(Component const& component, mpl::false_) const
+        bool dispatch_container(Component const& component, mpl::false_) const
         {
             // get the next value to generate from container
             if (!is_at_end() && !f(component, traits::deref(iter))) 
@@ -119,46 +271,20 @@
                 return false;
             }
 
-//             // in non-strict mode increment iterator if the underlying 
-//             // generator failed
-//             if (!Strict::value && !is_at_end())
-//                 traits::next(iter);
-
             // either no elements available any more or generation failed
             return true;
         }
 
-        // This is for the case when the current element expects an attribute
-        // which is a container itself, this element will get the rest of the 
-        // attribute container.
+        // this is for the case when the current element is able to handle an 
+        // attribute which is a container itself, this element will push its 
+        // data directly into the attribute container
         template <typename Component>
-        bool dispatch_attribute_element(Component const& component, mpl::true_) const
+        bool dispatch_container(Component const& component, mpl::true_) const
         {
             return f(component, make_iterator_range(iter, end));
         }
 
-        // This handles the distinction between elements in a sequence expecting
-        // containers themselves and elements expecting non-containers as their 
-        // attribute. Note: is_container treats optional<T>, where T is a 
-        // container as a container as well.
-        template <typename Component>
-        bool dispatch_attribute(Component const& component, mpl::true_) const
-        {
-            typedef typename traits::attribute_of<
-                Component, context_type>::type attribute_type;
-
-//             typedef mpl::and_<
-//                 traits::is_container<attribute_type>
-//               , is_convertible<Attr, attribute_type> > predicate;
-
-            typedef mpl::and_<
-                traits::is_container<attribute_type>
-              , traits::handles_container<Component, Attr, context_type>
-            > predicate;
-
-            return dispatch_attribute_element(component, predicate());
-        }
-
+        ///////////////////////////////////////////////////////////////////////
         // this is for the case when the current element doesn't expect an 
         // attribute
         template <typename Component>
@@ -167,30 +293,25 @@
             return f(component, unused);
         }
 
-        // This handles the case where the attribute of the component
-        // is not a STL container or which elements are not 
-        // convertible to the target attribute (Attr) value_type.
+        // the current element expects an attribute
         template <typename Component>
-        bool dispatch_main(Component const& component, mpl::false_) const
+        bool dispatch_attribute(Component const& component, mpl::true_) const
         {
-            // we need to dispatch again depending on the type of the attribute
-            // of the current element (component). If this is has no attribute
-            // we shouldn't use an element of the container but unused_type 
-            // instead
-            typedef traits::not_is_unused<
-                typename traits::attribute_of<Component, context_type>::type
+            typedef typename traits::container_value<Attr>::type value_type;
+            typedef typename 
+                traits::attribute_of<Component, context_type>::type
+            lhs_attribute;
+
+            // this predicate detects, whether the value type of the container
+            // attribute is a substitute for the attribute of the current 
+            // element 
+            typedef mpl::and_<
+                traits::handles_container<Component, Attr, context_type> 
+              , traits::pass_through_container<
+                    Attr, value_type, lhs_attribute, Sequence, karma::domain>
             > predicate;
 
-            return dispatch_attribute(component, predicate());
-        }
-
-        // This handles the case where the attribute of the component is
-        // an STL container *and* its value_type is convertible to the
-        // target attribute's (Attr) value_type.
-        template <typename Component>
-        bool dispatch_main(Component const& component, mpl::true_) const
-        {
-            return f(component, make_iterator_range(iter, end));
+            return dispatch_container(component, predicate());
         }
 
         // Dispatches to dispatch_main depending on the attribute type
@@ -198,19 +319,15 @@
         template <typename Component>
         bool operator()(Component const& component) const
         {
-            typedef typename traits::container_value<Attr>::type rhs;
-            typedef typename traits::attribute_of<
-                Component, context_type>::type lhs_attribute;
-
-            typedef mpl::and_<
-                mpl::or_<
-                    has_same_elements<rhs, lhs_attribute>
-                  , has_same_elements<Attr, lhs_attribute> >
-              , traits::handles_container<Component, Attr, context_type>
+            // we need to dispatch depending on the type of the attribute
+            // of the current element (component). If this is has no attribute
+            // we shouldn't use an element of the container but unused_type 
+            // instead
+            typedef traits::not_is_unused<
+                typename traits::attribute_of<Component, context_type>::type
             > predicate;
 
-            // false means everything went ok
-            return dispatch_main(component, predicate());
+            return dispatch_attribute(component, predicate());
         }
 
         F f;
@@ -221,14 +338,6 @@
         // silence MSVC warning C4512: assignment operator could not be generated
         pass_container& operator= (pass_container const&);
     };
-
-    // Utility function to make a pass_container
-    template <typename Strict, typename F, typename Attr, typename Iterator>
-    pass_container<F, Attr, Iterator, Strict>
-    inline make_pass_container(F const& f, Attr& attr, Iterator b, Iterator e)
-    {
-        return pass_container<F, Attr, Iterator, Strict>(f, attr, b, e);
-    }
 }}}}
 
 #endif
Modified: trunk/boost/spirit/home/karma/directive/repeat.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/directive/repeat.hpp	(original)
+++ trunk/boost/spirit/home/karma/directive/repeat.hpp	2011-03-20 14:23:49 EDT (Sun, 20 Mar 2011)
@@ -211,7 +211,7 @@
             indirect_iterator_type;
 
             typedef detail::pass_container<
-                fail_function, Attribute, indirect_iterator_type, Strict>
+                fail_function, Attribute, indirect_iterator_type, mpl::false_>
             pass_container;
 
             iterator_type it = traits::begin(attr);
Modified: trunk/boost/spirit/home/karma/operator/kleene.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/operator/kleene.hpp	(original)
+++ trunk/boost/spirit/home/karma/operator/kleene.hpp	2011-03-20 14:23:49 EDT (Sun, 20 Mar 2011)
@@ -111,7 +111,7 @@
                 typename traits::make_indirect_iterator<iterator_type>::type 
             indirect_iterator_type;
             typedef detail::pass_container<
-                fail_function, Attribute, indirect_iterator_type, Strict>
+                fail_function, Attribute, indirect_iterator_type, mpl::false_>
             pass_container;
 
             iterator_type it = traits::begin(attr);
Modified: trunk/boost/spirit/home/karma/operator/list.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/operator/list.hpp	(original)
+++ trunk/boost/spirit/home/karma/operator/list.hpp	2011-03-20 14:23:49 EDT (Sun, 20 Mar 2011)
@@ -117,7 +117,7 @@
                 typename traits::make_indirect_iterator<iterator_type>::type 
             indirect_iterator_type;
             typedef detail::pass_container<
-                fail_function, Attribute, indirect_iterator_type, Strict>
+                fail_function, Attribute, indirect_iterator_type, mpl::false_>
             pass_container;
 
             iterator_type it = traits::begin(attr);
Modified: trunk/boost/spirit/home/karma/operator/plus.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/operator/plus.hpp	(original)
+++ trunk/boost/spirit/home/karma/operator/plus.hpp	2011-03-20 14:23:49 EDT (Sun, 20 Mar 2011)
@@ -123,7 +123,7 @@
                 typename traits::make_indirect_iterator<iterator_type>::type 
             indirect_iterator_type;
             typedef detail::pass_container<
-                fail_function, Attribute, indirect_iterator_type, Strict>
+                fail_function, Attribute, indirect_iterator_type, mpl::false_>
             pass_container;
 
             iterator_type it = traits::begin(attr);
Modified: trunk/boost/spirit/home/karma/operator/sequence.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/operator/sequence.hpp	(original)
+++ trunk/boost/spirit/home/karma/operator/sequence.hpp	2011-03-20 14:23:49 EDT (Sun, 20 Mar 2011)
@@ -185,7 +185,7 @@
                 typename traits::make_indirect_iterator<iterator_type>::type 
             indirect_iterator_type;
             typedef detail::pass_container<
-                fail_function, Attribute, indirect_iterator_type, Strict>
+              fail_function, Attribute, indirect_iterator_type, mpl::true_>
             pass_container;
 
             iterator_type begin = traits::begin(attr_);
Modified: trunk/boost/spirit/home/qi/detail/pass_container.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/detail/pass_container.hpp	(original)
+++ trunk/boost/spirit/home/qi/detail/pass_container.hpp	2011-03-20 14:23:49 EDT (Sun, 20 Mar 2011)
@@ -26,13 +26,15 @@
 namespace boost { namespace spirit { namespace qi { namespace detail
 {
     // Helper meta-function allowing to evaluate weak substitutability and
-    // negate the result if the predicate is not true
+    // negate the result if the predicate (Sequence) is not true
     template <typename Sequence, typename Attribute, typename ValueType>
     struct negate_weak_substitute_if_not
       : mpl::if_<
             Sequence
           , typename traits::is_weak_substitute<Attribute, ValueType>::type
-          , typename mpl::not_<traits::is_weak_substitute<Attribute, ValueType> >::type>
+          , typename mpl::not_<
+                traits::is_weak_substitute<Attribute, ValueType> 
+            >::type>
     {};
 
     // pass_through_container: utility to check decide whether a provided 
@@ -115,8 +117,8 @@
       , bool IsSequence = fusion::traits::is_sequence<AttributeValueType>::value>
     struct pass_through_container_container
       : mpl::or_<
-          traits::is_weak_substitute<Attribute, Container> 
-        , traits::is_weak_substitute<AttributeValueType, Container> >
+            traits::is_weak_substitute<Attribute, Container> 
+          , traits::is_weak_substitute<AttributeValueType, Container> >
     {};
 
     // If the value type of the exposed container attribute is a Fusion
@@ -150,8 +152,8 @@
       , bool IsSequence = fusion::traits::is_sequence<Attribute>::value>
     struct pass_through_container_optional
       : mpl::or_<
-          traits::is_weak_substitute<Attribute, Container> 
-        , traits::is_weak_substitute<Attribute, ValueType> >
+            traits::is_weak_substitute<Attribute, Container> 
+          , traits::is_weak_substitute<Attribute, ValueType> >
     {};
 
     // If the embedded type of the exposed optional attribute is a Fusion
@@ -171,6 +173,7 @@
       : pass_through_container_base<Container, ValueType, Attribute, Sequence> 
     {};
 
+    // Handle optional attributes
     template <typename Container, typename ValueType, typename Attribute
       , typename Sequence>
     struct pass_through_container<
@@ -292,10 +295,10 @@
             // element is a substitute for the value type of the container
             // attribute 
             typedef mpl::and_<
-                traits::pass_through_container<
-                    Attr, value_type, rhs_attribute, Sequence, qi::domain>
-              , traits::handles_container<
+                traits::handles_container<
                     Component, Attr, context_type, iterator_type> 
+              , traits::pass_through_container<
+                    Attr, value_type, rhs_attribute, Sequence, qi::domain>
             > predicate;
 
             return dispatch_container(component, predicate());
Modified: trunk/boost/spirit/home/support/utree/utree_traits.hpp
==============================================================================
--- trunk/boost/spirit/home/support/utree/utree_traits.hpp	(original)
+++ trunk/boost/spirit/home/support/utree/utree_traits.hpp	2011-03-20 14:23:49 EDT (Sun, 20 Mar 2011)
@@ -38,11 +38,6 @@
     }
 }
 
-namespace boost { namespace spirit { namespace qi
-{
-    template <typename Subject> struct kleene;
-}}}
-
 ///////////////////////////////////////////////////////////////////////////////
 namespace boost { namespace spirit { namespace traits
 {
@@ -590,6 +585,9 @@
         // utree::list_type directly. Returning mpl::false_ from this meta 
         // function will force a new utree instance to be created for each
         // invocation of the embedded parser.
+
+        // The purpose of using utree::list_type as an attribute is to force a 
+        // new sub-node in the result.
         template <typename Attribute, typename Enable = void>
         struct handles_utree_list_container 
           : mpl::and_<
@@ -597,6 +595,9 @@
                 traits::is_container<Attribute> >
         {};
 
+        // The following specializations make sure that the actual handling of
+        // an utree (or utree::list_type) attribute is deferred to the embedded
+        // parsers of a sequence, alternative or optional component.
         template <typename Attribute>
         struct handles_utree_list_container<Attribute
               , typename enable_if<fusion::traits::is_sequence<Attribute> >::type>
@@ -671,13 +672,39 @@
     ///////////////////////////////////////////////////////////////////////////
     namespace detail
     {
-        // checks if the attr is utree
-        template <typename Attribute>
-        struct attribute_is_not_utree
+        // Checks whether the exposed Attribute allows to handle utree or 
+        // utree::list_type directly. Returning mpl::false_ from this meta 
+        // function will force a new utree instance to be created for each
+        // invocation of the embedded parser.
+
+        // The purpose of using utree::list_type as an attribute is to force a 
+        // new sub-node in the result.
+        template <typename Attribute, typename Enable = void>
+        struct handles_utree_container 
           : mpl::and_<
                 mpl::not_<is_same<utree, Attribute> >,
                 traits::is_container<Attribute> >
         {};
+
+        // The following specializations make sure that the actual handling of
+        // an utree (or utree::list_type) attribute is deferred to the embedded
+        // parsers of a sequence, alternative or optional component.
+        template <typename Attribute>
+        struct handles_utree_container<Attribute
+              , typename enable_if<fusion::traits::is_sequence<Attribute> >::type>
+          : mpl::true_
+        {};
+
+        template <typename Attribute>
+        struct handles_utree_container<boost::optional<Attribute> >
+          : mpl::true_
+        {};
+
+        template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
+        struct handles_utree_container<
+                boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
+          : mpl::true_
+        {};
     }
 
     template <
@@ -685,7 +712,7 @@
       , typename T1, typename T2, typename T3, typename T4>
     struct handles_container<karma::rule<IteratorA, T1, T2, T3, T4>
       , utree, Context, IteratorB>
-      : detail::attribute_is_not_utree<typename attribute_of<
+      : detail::handles_utree_container<typename attribute_of<
             karma::rule<IteratorA, T1, T2, T3, T4>, Context, IteratorB
         >::type>
     {};
@@ -695,12 +722,19 @@
       , typename T1, typename T2, typename T3, typename T4>
     struct handles_container<karma::grammar<IteratorA, T1, T2, T3, T4>
       , utree, Context, IteratorB>
-      : detail::attribute_is_not_utree<typename attribute_of<
+      : detail::handles_utree_container<typename attribute_of<
             karma::grammar<IteratorA, T1, T2, T3, T4>, Context, IteratorB
         >::type>
     {};
 
     ///////////////////////////////////////////////////////////////////////////
+    template <typename Attribute, typename Sequence>
+    struct pass_through_container<
+            utree, utree, Attribute, Sequence, karma::domain>
+      : detail::handles_utree_container<Attribute>
+    {};
+
+    ///////////////////////////////////////////////////////////////////////////
     // the specialization below tells Spirit how to handle utree if it is used
     // with an optional component
     template <>
@@ -1231,28 +1265,6 @@
     struct transform_attribute<utree::list_type const, Attribute, karma::domain>
       : transform_attribute<utree const, Attribute, karma::domain>
     {};
-
-#if 0
-    // If a rule takes an utree attribute and that utree instance holds nothing
-    // more than a list, we dereference this to simplify attribute handling 
-    // down the stream, i.e. ( ( 1 2 3 ) ) --> ( 1 2 3 ).
-    template <>
-    struct transform_attribute<utree const, utree, karma::domain>
-    {
-        typedef utree const& type;
-        static utree const& pre(utree const& val) 
-        { 
-            if (detail::is_list(val) && 1 == val.size())
-                return val.front();
-            return val; 
-        }
-    };
-
-    template <>
-    struct transform_attribute<utree const&, utree, karma::domain>
-      : transform_attribute<utree const, utree, karma::domain>
-    {};
-#endif
 }}}
 
 #endif