$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r61284 - in trunk: boost/spirit/home/karma/auxiliary boost/spirit/home/karma/nonterminal boost/spirit/home/karma/numeric boost/spirit/home/karma/string boost/spirit/home/qi/auxiliary boost/spirit/home/qi/nonterminal boost/spirit/home/support boost/spirit/repository/home/qi/nonterminal libs/spirit/doc/advanced libs/spirit/example/karma libs/spirit/example/qi libs/spirit/test/karma libs/spirit/test/qi
From: hartmut.kaiser_at_[hidden]
Date: 2010-04-14 22:43:25
Author: hkaiser
Date: 2010-04-14 22:43:23 EDT (Wed, 14 Apr 2010)
New Revision: 61284
URL: http://svn.boost.org/trac/boost/changeset/61284
Log:
Spirit: refining the transform_attribute CP
Text files modified: 
   trunk/boost/spirit/home/karma/auxiliary/attr_cast.hpp         |     3                                         
   trunk/boost/spirit/home/karma/nonterminal/rule.hpp            |    20 +++                                     
   trunk/boost/spirit/home/karma/numeric/bool_policies.hpp       |     2                                         
   trunk/boost/spirit/home/karma/string/symbols.hpp              |   119 ++++++++++++++++++++++++-               
   trunk/boost/spirit/home/qi/auxiliary/attr_cast.hpp            |     3                                         
   trunk/boost/spirit/home/qi/nonterminal/rule.hpp               |     6                                         
   trunk/boost/spirit/home/support/adapt_class_attributes.hpp    |     8                                         
   trunk/boost/spirit/home/support/attributes.hpp                |   179 ++++++++++++++++++++++++++------------- 
   trunk/boost/spirit/home/support/attributes_fwd.hpp            |     9 +                                       
   trunk/boost/spirit/repository/home/qi/nonterminal/subrule.hpp |     6                                         
   trunk/libs/spirit/doc/advanced/customization_points.qbk       |    20 +++-                                    
   trunk/libs/spirit/example/karma/reference.cpp                 |     2                                         
   trunk/libs/spirit/example/qi/reference.cpp                    |     2                                         
   trunk/libs/spirit/test/karma/attribute.cpp                    |     4                                         
   trunk/libs/spirit/test/karma/symbols.cpp                      |   112 ++++++++++++++++++++++++                
   trunk/libs/spirit/test/qi/attribute.cpp                       |     4                                         
   16 files changed, 400 insertions(+), 99 deletions(-)
Modified: trunk/boost/spirit/home/karma/auxiliary/attr_cast.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/auxiliary/attr_cast.hpp	(original)
+++ trunk/boost/spirit/home/karma/auxiliary/attr_cast.hpp	2010-04-14 22:43:23 EDT (Wed, 14 Apr 2010)
@@ -76,7 +76,8 @@
           , Attribute const& attr) const
         {
             typedef traits::transform_attribute<
-                Attribute const, transformed_attribute_type> transform;
+                Attribute const, transformed_attribute_type, domain> 
+            transform;
 
             return compile<karma::domain>(subject).generate(
                 sink, ctx, d, transform::pre(attr));
Modified: trunk/boost/spirit/home/karma/nonterminal/rule.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/nonterminal/rule.hpp	(original)
+++ trunk/boost/spirit/home/karma/nonterminal/rule.hpp	2010-04-14 22:43:23 EDT (Wed, 14 Apr 2010)
@@ -247,12 +247,18 @@
                 // Create an attribute if none is supplied. 
                 typedef traits::make_attribute<attr_type, Attribute> 
                     make_attribute;
+                typedef traits::transform_attribute<
+                    typename make_attribute::type, attr_type, domain> 
+                transform;
+
+                typename transform::type attr_ = 
+                    traits::pre_transform<domain, attr_type>(
+                        make_attribute::call(attr));
 
                 // If you are seeing a compilation error here, you are probably
                 // trying to use a rule or a grammar which has inherited
                 // attributes, without passing values for them.
-                context_type context(traits::pre_transform<attr_type>(
-                    make_attribute::call(attr)));
+                context_type context(attr_);
 
                 // If you are seeing a compilation error here stating that the 
                 // third parameter can't be converted to a karma::reference
@@ -281,12 +287,18 @@
                 // Create an attribute if none is supplied. 
                 typedef traits::make_attribute<attr_type, Attribute> 
                     make_attribute;
+                typedef traits::transform_attribute<
+                    typename make_attribute::type, attr_type, domain> 
+                transform;
+
+                typename transform::type attr_ = 
+                    traits::pre_transform<domain, attr_type>(
+                        make_attribute::call(attr));
 
                 // If you are seeing a compilation error here, you are probably
                 // trying to use a rule or a grammar which has inherited
                 // attributes, passing values of incompatible types for them.
-                context_type context(traits::pre_transform<attr_type>(
-                    make_attribute::call(attr)), params, caller_context);
+                context_type context(attr_, params, caller_context);
 
                 // If you are seeing a compilation error here stating that the 
                 // third parameter can't be converted to a karma::reference
Modified: trunk/boost/spirit/home/karma/numeric/bool_policies.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/numeric/bool_policies.hpp	(original)
+++ trunk/boost/spirit/home/karma/numeric/bool_policies.hpp	2010-04-14 22:43:23 EDT (Wed, 14 Apr 2010)
@@ -28,7 +28,7 @@
     //          //  we want to spell the names of false as eurt (true backwards)
     //          template <typename CharEncoding, typename Tag
     //            , typename OutputIterator>
-    //          static bool generate_flase(OutputIterator& sink, bool)
+    //          static bool generate_false(OutputIterator& sink, bool)
     //          {
     //              return string_inserter<CharEncoding, Tag>::call(sink, "eurt");
     //          }
Modified: trunk/boost/spirit/home/karma/string/symbols.hpp
==============================================================================
--- trunk/boost/spirit/home/karma/string/symbols.hpp	(original)
+++ trunk/boost/spirit/home/karma/string/symbols.hpp	2010-04-14 22:43:23 EDT (Wed, 14 Apr 2010)
@@ -30,6 +30,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 namespace boost { namespace spirit { namespace karma
 {
+    ///////////////////////////////////////////////////////////////////////////
     template <typename Attribute, typename T>
     struct symbols_lookup
       : mpl::if_<
@@ -40,6 +41,103 @@
     {};
 
     ///////////////////////////////////////////////////////////////////////////
+    namespace detail
+    {
+        ///////////////////////////////////////////////////////////////////////
+        template <typename CharEncoding, typename Tag>
+        struct generate_encoded
+        {
+            typedef typename 
+                proto::terminal<tag::char_code<Tag, CharEncoding> >::type
+            encoding_type;
+
+            template <typename OutputIterator, typename Expr, typename Attribute>
+            static bool call(OutputIterator& sink, Expr const& expr
+              , Attribute const& attr)
+            {
+                encoding_type const encoding = encoding_type();
+                return karma::generate(sink, encoding[expr], attr);
+            }
+        };
+
+        template <>
+        struct generate_encoded<unused_type, unused_type>
+        {
+            template <typename OutputIterator, typename Expr, typename Attribute>
+            static bool call(OutputIterator& sink, Expr const& expr
+              , Attribute const& attr)
+            {
+                return karma::generate(sink, expr, attr);
+            }
+        };
+
+        ///////////////////////////////////////////////////////////////////////
+        // extract first and second element of a fusion sequence
+        template <typename T>
+        struct first
+        {
+            typedef typename 
+                mpl::eval_if<fusion::traits::is_sequence<T>
+                  , fusion::result_of::value_at_c<T, 0>, mpl::identity<T> 
+            >::type type;
+            typedef typename add_reference<
+                typename add_const<type>::type
+            >::type result_type;
+
+            template <typename T_>
+            static result_type
+            call(T_ const& t, mpl::true_)
+            {
+                return fusion::at_c<0>(t);
+            }
+
+            template <typename T_>
+            static result_type
+            call(T_ const& t, mpl::false_)
+            {
+                return t;
+            }
+
+            static result_type
+            call(T const& t)
+            {
+                return call(t, fusion::traits::is_sequence<T>());
+            }
+        };
+
+        template <typename T>
+        struct second
+        {
+            typedef typename 
+                mpl::eval_if<fusion::traits::is_sequence<T>
+                  , fusion::result_of::value_at_c<T, 1>, mpl::identity<unused_type> 
+            >::type type;
+            typedef typename add_reference<
+                typename add_const<type>::type
+            >::type result_type;
+
+            template <typename T_>
+            static result_type
+            call(T_ const& t, mpl::true_)
+            {
+                return fusion::at_c<1>(t);
+            }
+
+            template <typename T_>
+            static result_type
+            call(T_ const& t, mpl::false_)
+            {
+                return unused;
+            }
+
+            static result_type
+            call(T const& t)
+            {
+                return call(t, fusion::traits::is_sequence<T>());
+            }
+        };
+    }
+
     template <
         typename Attribute = char, typename T = unused_type
       , typename Lookup = typename symbols_lookup<Attribute, T>::type
@@ -186,13 +284,15 @@
         bool generate(OutputIterator& sink, Context&, Delimiter const& d
           , Attr const& attr) const
         {
-            typename Lookup::iterator it = lookup->find(attr);
+            typename Lookup::iterator it = lookup->find(
+                detail::first<Attr>::call(attr));
             if (it == lookup->end())
                 return false;
 
-            return spirit::karma::detail::string_generate(
-                       sink, (*it).second, CharEncoding(), Tag()) &&
-                   spirit::karma::delimit_out(sink, d);
+            return karma::detail::generate_encoded<CharEncoding, Tag>::call(
+                        sink, (*it).second
+                      , detail::second<Attr>::call(attr)) && 
+                   karma::delimit_out(sink, d);
         }
 
         template <typename Context>
@@ -425,13 +525,16 @@
         bool generate(OutputIterator& sink, Context&, Delimiter const& d
           , Attr const& attr) const
         {
-            typename Lookup::iterator it = lookup->find(attr);
+            typename Lookup::iterator it = lookup->find(
+                detail::first<Attr>::call(attr));
             if (it == lookup->end())
                 return false;
 
-            return spirit::karma::detail::string_generate(
-                       sink, attr, CharEncoding(), Tag()) &&
-                   spirit::karma::delimit_out(sink, d);
+            return karma::detail::generate_encoded<CharEncoding, Tag>::
+                      call(sink
+                        , detail::first<Attr>::call(attr)
+                        , detail::second<Attr>::call(attr)) && 
+                   karma::delimit_out(sink, d);
         }
 
         template <typename Context>
Modified: trunk/boost/spirit/home/qi/auxiliary/attr_cast.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/auxiliary/attr_cast.hpp	(original)
+++ trunk/boost/spirit/home/qi/auxiliary/attr_cast.hpp	2010-04-14 22:43:23 EDT (Wed, 14 Apr 2010)
@@ -87,7 +87,8 @@
             // do down-stream transformation, provides attribute for embedded
             // parser
             typedef traits::transform_attribute<
-                exposed_attribute_type, transformed_attribute_type> transform;
+                exposed_attribute_type, transformed_attribute_type, domain> 
+            transform;
 
             typename transform::type attr_ = transform::pre(attr);
 
Modified: trunk/boost/spirit/home/qi/nonterminal/rule.hpp
==============================================================================
--- trunk/boost/spirit/home/qi/nonterminal/rule.hpp	(original)
+++ trunk/boost/spirit/home/qi/nonterminal/rule.hpp	2010-04-14 22:43:23 EDT (Wed, 14 Apr 2010)
@@ -246,7 +246,8 @@
                 // do down-stream transformation, provides attribute for
                 // rhs parser
                 typedef traits::transform_attribute<
-                    typename make_attribute::type, attr_type> transform;
+                    typename make_attribute::type, attr_type, domain> 
+                transform;
 
                 typename make_attribute::type made_attr = make_attribute::call(attr);
                 typename transform::type attr_ = transform::pre(made_attr);
@@ -291,7 +292,8 @@
                 // do down-stream transformation, provides attribute for
                 // rhs parser
                 typedef traits::transform_attribute<
-                    typename make_attribute::type, attr_type> transform;
+                    typename make_attribute::type, attr_type, domain> 
+                transform;
 
                 typename make_attribute::type made_attr = make_attribute::call(attr);
                 typename transform::type attr_ = transform::pre(made_attr);
Modified: trunk/boost/spirit/home/support/adapt_class_attributes.hpp
==============================================================================
--- trunk/boost/spirit/home/support/adapt_class_attributes.hpp	(original)
+++ trunk/boost/spirit/home/support/adapt_class_attributes.hpp	2010-04-14 22:43:23 EDT (Wed, 14 Apr 2010)
@@ -74,9 +74,9 @@
     {};
 
     ///////////////////////////////////////////////////////////////////////////
-    template <typename T, int N, typename Attribute>
+    template <typename T, int N, typename Attribute, typename Domain>
     struct transform_attribute<
-        fusion::extension::class_member_proxy<T, N>, Attribute
+        fusion::extension::class_member_proxy<T, N>, Attribute, Domain
       , typename disable_if<
             is_reference<typename fusion::extension::class_member_proxy<T, N>::lvalue> 
         >::type>
@@ -100,9 +100,9 @@
         }
     };
 
-    template <typename T, int N, typename Attribute>
+    template <typename T, int N, typename Attribute, typename Domain>
     struct transform_attribute<
-        fusion::extension::class_member_proxy<T, N>, Attribute
+        fusion::extension::class_member_proxy<T, N>, Attribute, Domain
       , typename enable_if<
             is_reference<typename fusion::extension::class_member_proxy<T, N>::lvalue> 
         >::type>
Modified: trunk/boost/spirit/home/support/attributes.hpp
==============================================================================
--- trunk/boost/spirit/home/support/attributes.hpp	(original)
+++ trunk/boost/spirit/home/support/attributes.hpp	2010-04-14 22:43:23 EDT (Wed, 14 Apr 2010)
@@ -17,6 +17,8 @@
 #include <boost/spirit/home/support/attributes_fwd.hpp>
 #include <boost/spirit/home/support/detail/hold_any.hpp>
 #include <boost/spirit/home/support/detail/as_variant.hpp>
+#include <boost/spirit/home/qi/domain.hpp>
+#include <boost/spirit/home/karma/domain.hpp>
 #include <boost/optional/optional.hpp>
 #include <boost/fusion/include/transform.hpp>
 #include <boost/fusion/include/filter_if.hpp>
@@ -49,7 +51,7 @@
 namespace boost { namespace spirit { namespace traits
 {
     ///////////////////////////////////////////////////////////////////////////
-    // This file deals with attribute related functions and metafunctions
+    // This file deals with attribute related functions and meta-functions
     // including generalized attribute transformation utilities for Spirit
     // components.
     ///////////////////////////////////////////////////////////////////////////
@@ -100,7 +102,8 @@
     namespace detail
     {
         //  A component is compatible to a given Attribute type if the
-        //  Attribute is the same as the expected type of the component
+        //  Attribute is the same as the expected type of the component or if 
+        //  it is convertible to the expected type.
         template <typename Expected, typename Attribute>
         struct attribute_is_compatible
           : is_convertible<Attribute, Expected>
@@ -197,7 +200,7 @@
     ///////////////////////////////////////////////////////////////////////////
     // attribute_not_unused
     //
-    // An mpl metafunction class that determines whether a component's
+    // An mpl meta-function class that determines whether a component's
     // attribute is not unused.
     ///////////////////////////////////////////////////////////////////////////
     template <typename Context, typename Iterator = unused_type>
@@ -552,32 +555,22 @@
         static void fail(Attribute&) {}
     };
 
-    template <typename Exposed, typename Transformed, typename Enable/* = void*/>
-    struct transform_attribute
-      : default_transform_attribute<Exposed, Transformed> {};
-
+    // main specialization for Qi
     template <typename Exposed, typename Transformed>
-    struct transform_attribute<Exposed, Transformed,
-        typename enable_if<
-                    mpl::and_<
-                        mpl::not_<is_const<Exposed> >,
-                        mpl::not_<is_reference<Exposed> >,
-                        is_proxy<Transformed>
-                    >
-                  >::type>
-            : proxy_transform_attribute<Exposed, Transformed> {};
-
-    template <typename Exposed, typename Transformed>
-    struct transform_attribute<Exposed const, Transformed>
-    {
-        typedef Transformed type;
-        static Transformed pre(Exposed const& val) { return Transformed(val); }
-        // Karma only, no post() and no fail() required
-    };
+    struct transform_attribute<Exposed, Transformed, qi::domain>
+      : mpl::if_<
+            mpl::and_<
+                mpl::not_<is_const<Exposed> >
+              , mpl::not_<is_reference<Exposed> >
+              , is_proxy<Transformed> >
+          , proxy_transform_attribute<Exposed, Transformed>
+          , default_transform_attribute<Exposed, Transformed> 
+        >::type 
+    {};
 
     template <typename Exposed, typename Transformed>
-    struct transform_attribute<optional<Exposed>, Transformed,
-        typename disable_if<is_same<optional<Exposed>, Transformed> >::type>
+    struct transform_attribute<optional<Exposed>, Transformed, qi::domain
+      , typename disable_if<is_same<optional<Exposed>, Transformed> >::type>
     {
         typedef Transformed& type;
         static Transformed& pre(optional<Exposed>& val)
@@ -593,22 +586,14 @@
         }
     };
 
-    template <typename Attribute>
-    struct transform_attribute<Attribute const, Attribute>
-    {
-        typedef Attribute const& type;
-        static Attribute const& pre(Attribute const& val) { return val; }
-        // Karma only, no post() and no fail() required
-    };
-
     // reference types need special handling
     template <typename Exposed, typename Transformed>
-    struct transform_attribute<Exposed&, Transformed>
-      : transform_attribute<Exposed, Transformed>
+    struct transform_attribute<Exposed&, Transformed, qi::domain>
+      : transform_attribute<Exposed, Transformed, qi::domain>
     {};
 
     template <typename Attribute>
-    struct transform_attribute<Attribute&, Attribute>
+    struct transform_attribute<Attribute&, Attribute, qi::domain>
     {
         typedef Attribute& type;
         static Attribute& pre(Attribute& val) { return val; }
@@ -616,73 +601,142 @@
         static void fail(Attribute&) {}
     };
 
+    // unused_type needs some special handling as well
+    template <>
+    struct transform_attribute<unused_type, unused_type, qi::domain>
+    {
+        typedef unused_type type;
+        static unused_type pre(unused_type) { return unused; }
+        static void post(unused_type, unused_type) {}
+        static void fail(unused_type) {}
+    };
+
+    template <>
+    struct transform_attribute<unused_type const, unused_type, qi::domain>
+      : transform_attribute<unused_type, unused_type, qi::domain>
+    {};
+
+    template <typename Attribute>
+    struct transform_attribute<unused_type, Attribute, qi::domain>
+      : transform_attribute<unused_type, unused_type, qi::domain>
+    {};
+
+    template <typename Attribute>
+    struct transform_attribute<unused_type const, Attribute, qi::domain>
+      : transform_attribute<unused_type, unused_type, qi::domain>
+    {};
+
+    template <typename Attribute>
+    struct transform_attribute<Attribute, unused_type, qi::domain>
+      : transform_attribute<unused_type, unused_type, qi::domain>
+    {};
+
+    template <typename Attribute>
+    struct transform_attribute<Attribute const, unused_type, qi::domain>
+      : transform_attribute<unused_type, unused_type, qi::domain>
+    {};
+
+    ///////////////////////////////////////////////////////////////////////////
+    template <typename Exposed, typename Transformed>
+    struct transform_attribute<Exposed, Transformed, karma::domain>
+    {
+        typedef Transformed type;
+        static Transformed pre(Exposed& val) { return Transformed(val); }
+        // Karma only, no post() and no fail() required
+    };
+
+    template <typename Exposed, typename Transformed>
+    struct transform_attribute<Exposed const, Transformed, karma::domain>
+    {
+        typedef Transformed type;
+        static Transformed pre(Exposed const& val) { return Transformed(val); }
+        // Karma only, no post() and no fail() required
+    };
+
     template <typename Attribute>
-    struct transform_attribute<Attribute const&, Attribute>
-      : transform_attribute<Attribute const, Attribute>
+    struct transform_attribute<Attribute const, Attribute, karma::domain>
+    {
+        typedef Attribute const& type;
+        static Attribute const& pre(Attribute const& val) { return val; }
+        // Karma only, no post() and no fail() required
+    };
+
+    // reference types need special handling
+    template <typename Exposed, typename Transformed>
+    struct transform_attribute<Exposed&, Transformed, karma::domain>
+      : transform_attribute<Exposed, Transformed, karma::domain>
+    {};
+
+    template <typename Exposed, typename Transformed>
+    struct transform_attribute<Exposed const&, Transformed, karma::domain>
+      : transform_attribute<Exposed const, Transformed, karma::domain>
+    {};
+
+    template <typename Attribute>
+    struct transform_attribute<Attribute const&, Attribute, karma::domain>
+      : transform_attribute<Attribute const, Attribute, karma::domain>
     {};
 
     // unused_type needs some special handling as well
     template <>
-    struct transform_attribute<unused_type, unused_type>
+    struct transform_attribute<unused_type, unused_type, karma::domain>
     {
         typedef unused_type type;
         static unused_type pre(unused_type) { return unused; }
-        static void post(unused_type, unused_type) {}
-        static void fail(unused_type) {}
     };
 
     template <>
-    struct transform_attribute<unused_type const, unused_type>
-      : transform_attribute<unused_type, unused_type>
+    struct transform_attribute<unused_type const, unused_type, karma::domain>
+      : transform_attribute<unused_type, unused_type, karma::domain>
     {};
 
     template <typename Attribute>
-    struct transform_attribute<unused_type, Attribute>
-      : transform_attribute<unused_type, unused_type>
+    struct transform_attribute<unused_type, Attribute, karma::domain>
+      : transform_attribute<unused_type, unused_type, karma::domain>
     {};
 
     template <typename Attribute>
-    struct transform_attribute<unused_type const, Attribute>
-      : transform_attribute<unused_type, unused_type>
+    struct transform_attribute<unused_type const, Attribute, karma::domain>
+      : transform_attribute<unused_type, unused_type, karma::domain>
     {};
 
     template <typename Attribute>
-    struct transform_attribute<Attribute, unused_type>
-      : transform_attribute<unused_type, unused_type>
+    struct transform_attribute<Attribute, unused_type, karma::domain>
+      : transform_attribute<unused_type, unused_type, karma::domain>
     {};
 
     template <typename Attribute>
-    struct transform_attribute<Attribute const, unused_type>
-      : transform_attribute<unused_type, unused_type>
+    struct transform_attribute<Attribute const, unused_type, karma::domain>
+      : transform_attribute<unused_type, unused_type, karma::domain>
     {};
 
     ///////////////////////////////////////////////////////////////////////////
-    template <typename Transformed, typename Exposed>
-    typename spirit::result_of::pre_transform<Exposed, Transformed>::type
+    template <typename Domain, typename Transformed, typename Exposed>
+    typename spirit::result_of::pre_transform<Exposed, Transformed, Domain>::type
     pre_transform(Exposed& attr BOOST_PROTO_DISABLE_IF_IS_CONST(Exposed))
     {
-        return transform_attribute<Exposed, Transformed>::pre(attr);
+        return transform_attribute<Exposed, Transformed, Domain>::pre(attr);
     }
 
-    template <typename Transformed, typename Exposed>
-    typename spirit::result_of::pre_transform<Exposed const, Transformed>::type
+    template <typename Domain, typename Transformed, typename Exposed>
+    typename spirit::result_of::pre_transform<Exposed const, Transformed, Domain>::type
     pre_transform(Exposed const& attr)
     {
-        return transform_attribute<Exposed const, Transformed>::pre(attr);
+        return transform_attribute<Exposed const, Transformed, Domain>::pre(attr);
     }
 
     ///////////////////////////////////////////////////////////////////////////
     template <typename Exposed, typename Transformed>
     void post_transform(Exposed& dest, Transformed const& attr)
     {
-        return transform_attribute<Exposed, Transformed>::post(dest, attr);
+        return transform_attribute<Exposed, Transformed, qi::domain>::post(dest, attr);
     }
 
     ///////////////////////////////////////////////////////////////////////////
     template <typename Exposed, typename Transformed>
     void fail_transform(Exposed& dest, Transformed const&)
     {
-        return transform_attribute<Exposed, Transformed>::fail(dest);
+        return transform_attribute<Exposed, Transformed, qi::domain>::fail(dest);
     }
 
     ///////////////////////////////////////////////////////////////////////////
@@ -918,6 +972,7 @@
     {
     }
 
+    ///////////////////////////////////////////////////////////////////////////
     template <typename Out, typename T>
     void print_attribute(Out& out, T const& val);
 
@@ -997,9 +1052,9 @@
 ///////////////////////////////////////////////////////////////////////////////
 namespace boost { namespace spirit { namespace result_of
 {
-    template <typename Exposed, typename Transformed>
+    template <typename Exposed, typename Transformed, typename Domain>
     struct pre_transform
-      : traits::transform_attribute<Exposed, Transformed>
+      : traits::transform_attribute<Exposed, Transformed, Domain>
     {};
 }}}
 
Modified: trunk/boost/spirit/home/support/attributes_fwd.hpp
==============================================================================
--- trunk/boost/spirit/home/support/attributes_fwd.hpp	(original)
+++ trunk/boost/spirit/home/support/attributes_fwd.hpp	2010-04-14 22:43:23 EDT (Wed, 14 Apr 2010)
@@ -49,10 +49,12 @@
     // the user is able specify specific transformation rules for any attribute
     // type.
     ///////////////////////////////////////////////////////////////////////////
-    template <typename Exposed, typename Transformed, typename Enable = void>
+    template <typename Exposed, typename Transformed, typename Domain
+      , typename Enable = void>
     struct transform_attribute;
 
     ///////////////////////////////////////////////////////////////////////////
+    // Qi only
     template <typename Attribute, typename Iterator, typename Enable = void>
     struct assign_to_attribute_from_iterators;
 
@@ -60,6 +62,7 @@
     struct assign_to_attribute_from_value;
 
     ///////////////////////////////////////////////////////////////////////////
+    // Karma only
     template <typename Attribute, typename Enable = void>
     struct extract_from_attribute;
 
@@ -82,6 +85,7 @@
     struct is_container;
 
     ///////////////////////////////////////////////////////////////////////////
+    // Qi only
     template <typename Container, typename T, typename Enable = void>
     struct push_back_container;
 
@@ -90,6 +94,7 @@
 
     ///////////////////////////////////////////////////////////////////////
     // Determine the iterator type of the given container type
+    // Karma only
     ///////////////////////////////////////////////////////////////////////
     template <typename Container, typename Enable = void>
     struct begin_container;
@@ -114,7 +119,7 @@
     template <typename Attribute>
     struct extract_from;
 
-    template <typename Exposed, typename Transformed>
+    template <typename Exposed, typename Transformed, typename Domain>
     struct pre_transform;
 
     template <typename T>
Modified: trunk/boost/spirit/repository/home/qi/nonterminal/subrule.hpp
==============================================================================
--- trunk/boost/spirit/repository/home/qi/nonterminal/subrule.hpp	(original)
+++ trunk/boost/spirit/repository/home/qi/nonterminal/subrule.hpp	2010-04-14 22:43:23 EDT (Wed, 14 Apr 2010)
@@ -202,7 +202,8 @@
             // do down-stream transformation, provides attribute for 
             // rhs parser
             typedef traits::transform_attribute<
-                typename make_attribute::type, subrule_attr_type> transform;
+                typename make_attribute::type, subrule_attr_type, domain> 
+            transform;
 
             typename make_attribute::type made_attr = make_attribute::call(attr);
             typename transform::type attr_ = transform::pre(made_attr);
@@ -255,7 +256,8 @@
             // do down-stream transformation, provides attribute for 
             // rhs parser
             typedef traits::transform_attribute<
-                typename make_attribute::type, subrule_attr_type> transform;
+                typename make_attribute::type, subrule_attr_type, domain> 
+            transform;
 
             typename make_attribute::type made_attr = make_attribute::call(attr);
             typename transform::type attr_ = transform::pre(made_attr);
Modified: trunk/libs/spirit/doc/advanced/customization_points.qbk
==============================================================================
--- trunk/libs/spirit/doc/advanced/customization_points.qbk	(original)
+++ trunk/libs/spirit/doc/advanced/customization_points.qbk	2010-04-14 22:43:23 EDT (Wed, 14 Apr 2010)
@@ -217,6 +217,10 @@
 provided attribute to the attribute type expected by the right hand side 
 component (for `rule`) or the embedded component (for `attr_cast`).
 
+[note The interface of this customization point has been changed with Boost 
+      V1.44. We added the `Domain` template parameter to allow for more fine 
+      grained specializations for __qi__ and __karma__.]
+
 [heading Module Headers]
 
     #include <boost/spirit/home/support/attributes.hpp>
@@ -236,7 +240,7 @@
 
 [heading Synopsis]
 
-    template <typename Exposed, typename Transformed, typename Enable>
+    template <typename Exposed, typename Transformed, typename Domain, typename Enable>
     struct transform_attribute
     {
         typedef <unspecified> type;
@@ -253,6 +257,9 @@
                              which needs to be transformed.]    [none]]
     [[`Transformed`]        [The attribute type expected by the component
                              to be provided as the result of the transformation.] [none]]
+    [[`Domain`]             [The domain of the sub library the template is 
+                             instantiated in. Typically this is either `qi::domain`
+                             or `karma::domain`.]        [none]]
     [[`Enable`]             [Helper template parameter usable to selectively
                              enable or disable certain specializations
                              of `transform_attribute` utilizing SFINAE (i.e.
@@ -267,6 +274,9 @@
     [[`Transformed`]      [The type, `Transformed` is the type of the attribute 
                            as passed along to the right hand side of the `rule`
                            (embedded component of `attr_cast`).]]
+    [[`Domain`]             [The domain of the sub library the template is 
+                             instantiated in. Typically this is either `qi::domain`
+                             or `karma::domain`.]]
     [[`exposed`]          [An instance of type `Exposed`.]]
     [[`transformed`]      [An instance of type `Transformed`.]]
 ]
@@ -275,7 +285,7 @@
 
 [table
     [[Expression]       [Semantics]]
-    [[`transform_attribute<Exposed, Transformed>::type`] 
+    [[`transform_attribute<Exposed, Transformed, Domain>::type`] 
                         [Evaluates to the type to be used as the result of the 
                          transformation (to be passed to the right hand side of
                          the `rule` or to the embedded component of the 
@@ -284,7 +294,7 @@
                          `Transformed&` instead avoiding superfluous object
                          creation.]]
     [[
-``type transform_attribute<Exposed, Transformed>::pre(exposed)``]
+``type transform_attribute<Exposed, Transformed, Domain>::pre(exposed)``]
                         [Do `pre`-transformation before invoking the right hand
                          side component for `rule` (or the embedded component 
                          for `attr_cast`). This takes the attribute supplied as by
@@ -293,7 +303,7 @@
                          as exposed by the metafunction `type`). This function
                          will be called in /Qi/ and for /Karma/.]]
     [[
-``void transform_attribute<Exposed, Transformed>::post(exposed, transformed)``]
+``void transform_attribute<Exposed, Transformed, Domain>::post(exposed, transformed)``]
                         [Do `post`-transformation after the invocation of the 
                          right hand side component for `rule` (or the embedded 
                          component for `attr_cast`). This takes the original 
@@ -303,7 +313,7 @@
                          into the supplied attribute instance. This function 
                          will be called in /Qi/ only.]]
     [[
-``void transform_attribute<Exposed, Transformed>::fail(exposed)``]
+``void transform_attribute<Exposed, Transformed, Domain>::fail(exposed)``]
                         [Handling failing parse operations of the
                          right hand side component for `rule` (or the embedded 
                          component for `attr_cast`). This function 
Modified: trunk/libs/spirit/example/karma/reference.cpp
==============================================================================
--- trunk/libs/spirit/example/karma/reference.cpp	(original)
+++ trunk/libs/spirit/example/karma/reference.cpp	2010-04-14 22:43:23 EDT (Wed, 14 Apr 2010)
@@ -183,7 +183,7 @@
 namespace boost { namespace spirit { namespace traits
 {
     template <>
-    struct transform_attribute<int_data const, int>
+    struct transform_attribute<int_data const, int, karma::domain>
     {
         typedef int type;
         static int pre(int_data const& d) { return d.i; }
Modified: trunk/libs/spirit/example/qi/reference.cpp
==============================================================================
--- trunk/libs/spirit/example/qi/reference.cpp	(original)
+++ trunk/libs/spirit/example/qi/reference.cpp	2010-04-14 22:43:23 EDT (Wed, 14 Apr 2010)
@@ -281,7 +281,7 @@
     // in this case we just expose the embedded 'int' as the attribute instance 
     // to use, allowing to leave the function 'post()' empty
     template <>
-    struct transform_attribute<int_data, int>
+    struct transform_attribute<int_data, int, qi::domain>
     {
         typedef int& type;
         static int& pre(int_data& d) { return d.i; }
Modified: trunk/libs/spirit/test/karma/attribute.cpp
==============================================================================
--- trunk/libs/spirit/test/karma/attribute.cpp	(original)
+++ trunk/libs/spirit/test/karma/attribute.cpp	2010-04-14 22:43:23 EDT (Wed, 14 Apr 2010)
@@ -49,7 +49,7 @@
 namespace boost { namespace spirit { namespace traits
 {
     template <>
-    struct transform_attribute<test_int_data1 const, int>
+    struct transform_attribute<test_int_data1 const, int, karma::domain>
     {
         typedef int type;
         static int pre(test_int_data1 const& d) { return d.i; }
@@ -68,7 +68,7 @@
 namespace boost { namespace spirit { namespace traits
 {
     template <>
-    struct transform_attribute<test_int_data2 const, int>
+    struct transform_attribute<test_int_data2 const, int, karma::domain>
     {
         typedef int const& type;
         static int const& pre(test_int_data2 const& d) { return d.i; }
Modified: trunk/libs/spirit/test/karma/symbols.cpp
==============================================================================
--- trunk/libs/spirit/test/karma/symbols.cpp	(original)
+++ trunk/libs/spirit/test/karma/symbols.cpp	2010-04-14 22:43:23 EDT (Wed, 14 Apr 2010)
@@ -12,9 +12,12 @@
 #include <boost/spirit/include/karma_operator.hpp>
 #include <boost/spirit/include/karma_directive.hpp>
 #include <boost/spirit/include/karma_generate.hpp>
+#include <boost/spirit/include/karma_nonterminal.hpp>
 
 #include "test.hpp"
 
+namespace fusion = boost::fusion;
+
 int main()
 {
     using spirit_test::test;
@@ -65,6 +68,113 @@
         BOOST_TEST((!test("", sym, 'h')));
     }
 
+    { // advanced
+        using boost::spirit::karma::rule;
+        using boost::spirit::karma::lit;
+
+        typedef spirit_test::output_iterator<char>::type output_iterator_type;
+
+        symbols<char, rule<output_iterator_type> > sym;
+
+        rule<output_iterator_type> r1 = lit("Joel");
+        rule<output_iterator_type> r2 = lit("Hartmut");
+        rule<output_iterator_type> r3 = lit("Tom");
+        rule<output_iterator_type> r4 = lit("Kim");
+        
+        sym.add
+            ('j', r1.alias())
+            ('h', r2.alias())
+            ('t', r3.alias())
+            ('k', r4.alias())
+        ;
+
+        boost::mpl::true_ f = 
+            boost::mpl::bool_<boost::spirit::traits::is_generator<
+                symbols<char, rule<output_iterator_type> > >::value>();
+
+        // silence stupid compiler warnings 
+        // i.e. MSVC warning C4189: 'f' : local variable is initialized but not referenced
+        BOOST_TEST((f.value));
+
+        BOOST_TEST((test("Joel", sym, 'j')));
+        BOOST_TEST((test("Hartmut", sym, 'h')));
+        BOOST_TEST((test("Tom", sym, 't')));
+        BOOST_TEST((test("Kim", sym, 'k')));
+        BOOST_TEST((!test("", sym, 'x')));
+
+        // test copy
+        symbols<char, rule<output_iterator_type> > sym2;
+        sym2 = sym;
+        BOOST_TEST((test("Joel", sym2, 'j')));
+        BOOST_TEST((test("Hartmut", sym2, 'h')));
+        BOOST_TEST((test("Tom", sym2, 't')));
+        BOOST_TEST((test("Kim", sym2, 'k')));
+        BOOST_TEST((!test("", sym2, 'x')));
+
+        // make sure it plays well with other generators
+        BOOST_TEST((test("Joelyo", sym << "yo", 'j')));
+
+        sym.remove
+            ('j')
+            ('h')
+        ;
+
+        BOOST_TEST((!test("", sym, 'j')));
+        BOOST_TEST((!test("", sym, 'h')));
+    }
+
+    { // more advanced
+        using boost::spirit::karma::rule;
+        using boost::spirit::karma::lit;
+        using boost::spirit::karma::string;
+
+        typedef spirit_test::output_iterator<char>::type output_iterator_type;
+
+        symbols<char, rule<output_iterator_type, std::string()> > sym;
+        rule<output_iterator_type, std::string()> r1 = string;
+        
+        sym.add
+            ('j', r1.alias())
+            ('h', r1.alias())
+            ('t', r1.alias())
+            ('k', r1.alias())
+        ;
+
+        boost::mpl::true_ f = 
+            boost::mpl::bool_<boost::spirit::traits::is_generator<
+                symbols<char, std::string> >::value>();
+
+        // silence stupid compiler warnings 
+        // i.e. MSVC warning C4189: 'f' : local variable is initialized but not referenced
+        BOOST_TEST((f.value));
+
+        BOOST_TEST((test("Joel", sym, fusion::make_vector('j', "Joel"))));
+        BOOST_TEST((test("Hartmut", sym, fusion::make_vector('h', "Hartmut"))));
+        BOOST_TEST((test("Tom", sym, fusion::make_vector('t', "Tom"))));
+        BOOST_TEST((test("Kim", sym, fusion::make_vector('k', "Kim"))));
+        BOOST_TEST((!test("", sym, 'x')));
+
+        // test copy
+        symbols<char, rule<output_iterator_type, std::string()> > sym2;
+        sym2 = sym;
+        BOOST_TEST((test("Joel", sym2, fusion::make_vector('j', "Joel"))));
+        BOOST_TEST((test("Hartmut", sym2, fusion::make_vector('h', "Hartmut"))));
+        BOOST_TEST((test("Tom", sym2, fusion::make_vector('t', "Tom"))));
+        BOOST_TEST((test("Kim", sym2, fusion::make_vector('k', "Kim"))));
+        BOOST_TEST((!test("", sym2, 'x')));
+
+        // make sure it plays well with other generators
+        BOOST_TEST((test("Joelyo", sym << "yo", fusion::make_vector('j', "Joel"))));
+
+        sym.remove
+            ('j')
+            ('h')
+        ;
+
+        BOOST_TEST((!test("", sym, 'j')));
+        BOOST_TEST((!test("", sym, 'h')));
+    }
+
     { // basics
         symbols<std::string> sym;
 
@@ -110,7 +220,7 @@
         BOOST_TEST((!test("", sym, "Hartmut")));
     }
 
-    { // no-case handling
+    { // lower/upper handling
         using namespace boost::spirit::ascii;
         using boost::spirit::karma::lower;
         using boost::spirit::karma::upper;
Modified: trunk/libs/spirit/test/qi/attribute.cpp
==============================================================================
--- trunk/libs/spirit/test/qi/attribute.cpp	(original)
+++ trunk/libs/spirit/test/qi/attribute.cpp	2010-04-14 22:43:23 EDT (Wed, 14 Apr 2010)
@@ -54,7 +54,7 @@
 namespace boost { namespace spirit { namespace traits
 {
     template <>
-    struct transform_attribute<test_int_data1, int>
+    struct transform_attribute<test_int_data1, int, qi::domain>
     {
         typedef int type;
         static int pre(test_int_data1& d) { return d.i; }
@@ -74,7 +74,7 @@
 namespace boost { namespace spirit { namespace traits
 {
     template <>
-    struct transform_attribute<test_int_data2, int>
+    struct transform_attribute<test_int_data2, int, qi::domain>
     {
         typedef int& type;
         static int& pre(test_int_data2& d) { return d.i; }