$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r61859 - trunk/boost/proto
From: eric_at_[hidden]
Date: 2010-05-08 18:27:41
Author: eric_niebler
Date: 2010-05-08 18:27:39 EDT (Sat, 08 May 2010)
New Revision: 61859
URL: http://svn.boost.org/trac/boost/changeset/61859
Log:
add partial support for sub-domains. Full support (on compilers supporting Boost.TypeOf) to come
Text files modified: 
   trunk/boost/proto/domain.hpp       |   449 +++++++++++++++++++++++++-------------- 
   trunk/boost/proto/make_expr.hpp    |   100 --------                                
   trunk/boost/proto/operators.hpp    |    30 --                                      
   trunk/boost/proto/proto_fwd.hpp    |    10                                         
   trunk/boost/proto/proto_typeof.hpp |     5                                         
   5 files changed, 310 insertions(+), 284 deletions(-)
Modified: trunk/boost/proto/domain.hpp
==============================================================================
--- trunk/boost/proto/domain.hpp	(original)
+++ trunk/boost/proto/domain.hpp	2010-05-08 18:27:39 EDT (Sat, 08 May 2010)
@@ -1,174 +1,305 @@
-///////////////////////////////////////////////////////////////////////////////
-/// \file domain.hpp
-/// Contains definition of domain\<\> class template and helpers for
-/// defining domains with a generator and a grammar for controlling
-/// operator overloading.
-//
-//  Copyright 2008 Eric Niebler. Distributed under the Boost
-//  Software License, Version 1.0. (See accompanying file
-//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-
-#ifndef BOOST_PROTO_DOMAIN_HPP_EAN_02_13_2007
-#define BOOST_PROTO_DOMAIN_HPP_EAN_02_13_2007
-
-#include <boost/ref.hpp>
-#include <boost/mpl/bool.hpp>
-#include <boost/proto/proto_fwd.hpp>
-#include <boost/proto/generate.hpp>
+#ifndef BOOST_PP_IS_ITERATING
+    ///////////////////////////////////////////////////////////////////////////////
+    /// \file domain.hpp
+    /// Contains definition of domain\<\> class template and helpers for
+    /// defining domains with a generator and a grammar for controlling
+    /// operator overloading.
+    //
+    //  Copyright 2008 Eric Niebler. Distributed under the Boost
+    //  Software License, Version 1.0. (See accompanying file
+    //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+
+    #ifndef BOOST_PROTO_DOMAIN_HPP_EAN_02_13_2007
+    #define BOOST_PROTO_DOMAIN_HPP_EAN_02_13_2007
+
+    #include <boost/ref.hpp>
+    #include <boost/mpl/bool.hpp>
+    #include <boost/mpl/assert.hpp>
+    #include <boost/preprocessor/cat.hpp>
+    #include <boost/preprocessor/facilities/intercept.hpp>
+    #include <boost/preprocessor/iteration/iterate.hpp>
+    #include <boost/preprocessor/repetition/repeat.hpp>
+    #include <boost/preprocessor/repetition/enum_trailing_params.hpp>
+    #include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp>
+    #include <boost/preprocessor/repetition/enum_params.hpp>
+    #include <boost/preprocessor/arithmetic/inc.hpp>
+    #include <boost/preprocessor/arithmetic/dec.hpp>
+    #include <boost/preprocessor/arithmetic/add.hpp>
+    #include <boost/preprocessor/control/expr_if.hpp>
+    #include <boost/proto/proto_fwd.hpp>
+    #include <boost/proto/generate.hpp>
+
+    #ifdef _MSC_VER
+    #define BOOST_PROTO_DISABLE_MSVC_C4584 __pragma(warning(disable: 4584))
+    #else
+    #define BOOST_PROTO_DISABLE_MSVC_C4584 
+    #endif
 
-namespace boost { namespace proto
-{
-
-    namespace detail
+    namespace boost { namespace proto
     {
-        struct not_a_generator
-        {};
-
-        struct not_a_grammar
-        {};
-    }
 
-    namespace domainns_
-    {
-        /// \brief For use in defining domain tags to be used
-        /// with \c proto::extends\<\>. A \e Domain associates
-        /// an expression type with a \e Generator, and optionally
-        /// a \e Grammar.
-        ///
-        /// The Generator determines how new expressions in the
-        /// domain are constructed. Typically, a generator wraps
-        /// all new expressions in a wrapper that imparts
-        /// domain-specific behaviors to expressions within its
-        /// domain. (See \c proto::extends\<\>.)
-        ///
-        /// The Grammar determines whether a given expression is
-        /// valid within the domain, and automatically disables
-        /// any operator overloads which would cause an invalid
-        /// expression to be created. By default, the Grammar
-        /// parameter defaults to the wildcard, \c proto::_, which
-        /// makes all expressions valid within the domain.
-        ///
-        /// Example:
-        /// \code
-        /// template<typename Expr>
-        /// struct MyExpr;
-        ///
-        /// struct MyGrammar
-        ///   : or_< terminal<_>, plus<MyGrammar, MyGrammar> >
-        /// {};
-        ///
-        /// // Define MyDomain, in which all expressions are
-        /// // wrapped in MyExpr<> and only expressions that
-        /// // conform to MyGrammar are allowed.
-        /// struct MyDomain
-        ///   : domain<generator<MyExpr>, MyGrammar>
-        /// {};
-        ///
-        /// // Use MyDomain to define MyExpr
-        /// template<typename Expr>
-        /// struct MyExpr
-        ///   : extends<Expr, MyExpr<Expr>, MyDomain>
-        /// {
-        ///     // ...
-        /// };
-        /// \endcode
-        ///
-        template<
-            typename Generator // = default_generator
-          , typename Grammar   // = proto::_
-        >
-        struct domain
-          : Generator
+        namespace detail
         {
-            typedef Generator proto_generator;
-            typedef Grammar proto_grammar;
+            struct not_a_generator
+            {};
 
-            /// INTERNAL ONLY
-            typedef void proto_is_domain_;
-        };
+            struct not_a_grammar
+            {};
 
-        /// \brief The domain expressions have by default, if
-        /// \c proto::extends\<\> has not been used to associate
-        /// a domain with an expression.
-        ///
-        struct default_domain
-          : domain<>
-        {};
-
-        /// \brief A pseudo-domain for use in functions and
-        /// metafunctions that require a domain parameter. It
-        /// indicates that the domain of the parent node should
-        /// be inferred from the domains of the child nodes.
-        ///
-        /// \attention \c deduce_domain is not itself a valid domain.
-        ///
-        struct deduce_domain
-          : domain<detail::not_a_generator, detail::not_a_grammar>
-        {};
-    }
+            struct not_a_domain
+            {};
 
-    namespace result_of
-    {
-        /// A metafunction that returns \c mpl::true_
-        /// if the type \c T is the type of a Proto domain;
-        /// \c mpl::false_ otherwise. If \c T inherits from
-        /// \c proto::domain\<\>, \c is_domain\<T\> is
-        /// \c mpl::true_.
-        template<typename T, typename Void  /* = void*/>
-        struct is_domain
-          : mpl::false_
-        {};
-
-        /// INTERNAL ONLY
-        ///
-        template<typename T>
-        struct is_domain<T, typename T::proto_is_domain_>
-          : mpl::true_
-        {};
-
-        /// A metafunction that returns the domain of
-        /// a given type. If \c T is a Proto expression
-        /// type, it returns that expression's associated
-        /// domain. If not, it returns
-        /// \c proto::default_domain.
-        template<typename T, typename Void /* = void*/>
-        struct domain_of
-        {
-            typedef default_domain type;
-        };
+            template<typename Super>
+            struct super_domain : super_domain<typename Super::super>
+            {
+                typedef Super super;
+                using super_domain<typename Super::super>::test;
+                super_domain test(super_domain);
+                super_domain test(super_domain<default_domain> const &);
+                super *& get_super();
+            };
+
+            template<>
+            struct super_domain<not_a_domain>
+            {
+                typedef not_a_domain super;
+                super_domain test(...);
+                super *& get_super();
+            };
+
+            template<>
+            struct super_domain<default_domain>
+            {
+                typedef default_domain super;
+                template<typename T> T test(T);
+                super *& get_super();
+            };
+
+            template<typename T, int N> char (&select_domain(T*&))[N];
+            template<typename T, int N> char (&select_domain(...))[1];
+
+            template<
+                int Index
+                BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(
+                    BOOST_PROTO_MAX_ARITY
+                  , typename D
+                  , = void BOOST_PP_INTERCEPT
+                )
+            >
+            struct select_nth
+            {
+                BOOST_MPL_ASSERT_MSG((false), PROTO_DOMAIN_MISMATCH, (select_nth));
+                typedef not_a_domain type;
+            };
+
+            template<typename Void = void>
+            struct deduce_domain0
+            {
+                typedef default_domain type;
+            };
+
+            #define BOOST_PP_ITERATION_PARAMS_1 (3, (1, BOOST_PROTO_MAX_ARITY, <boost/proto/domain.hpp>))
+            #include BOOST_PP_ITERATE()
+        }
 
-        /// INTERNAL ONLY
-        ///
-        template<typename T>
-        struct domain_of<T, typename T::proto_is_expr_>
+        namespace domainns_
         {
-            typedef typename T::proto_domain type;
-        };
+            /// \brief For use in defining domain tags to be used
+            /// with \c proto::extends\<\>. A \e Domain associates
+            /// an expression type with a \e Generator, and optionally
+            /// a \e Grammar.
+            ///
+            /// The Generator determines how new expressions in the
+            /// domain are constructed. Typically, a generator wraps
+            /// all new expressions in a wrapper that imparts
+            /// domain-specific behaviors to expressions within its
+            /// domain. (See \c proto::extends\<\>.)
+            ///
+            /// The Grammar determines whether a given expression is
+            /// valid within the domain, and automatically disables
+            /// any operator overloads which would cause an invalid
+            /// expression to be created. By default, the Grammar
+            /// parameter defaults to the wildcard, \c proto::_, which
+            /// makes all expressions valid within the domain.
+            ///
+            /// Example:
+            /// \code
+            /// template<typename Expr>
+            /// struct MyExpr;
+            ///
+            /// struct MyGrammar
+            ///   : or_< terminal<_>, plus<MyGrammar, MyGrammar> >
+            /// {};
+            ///
+            /// // Define MyDomain, in which all expressions are
+            /// // wrapped in MyExpr<> and only expressions that
+            /// // conform to MyGrammar are allowed.
+            /// struct MyDomain
+            ///   : domain<generator<MyExpr>, MyGrammar>
+            /// {};
+            ///
+            /// // Use MyDomain to define MyExpr
+            /// template<typename Expr>
+            /// struct MyExpr
+            ///   : extends<Expr, MyExpr<Expr>, MyDomain>
+            /// {
+            ///     // ...
+            /// };
+            /// \endcode
+            ///
+            BOOST_PROTO_DISABLE_MSVC_C4584
+            template<
+                typename Generator // = default_generator
+              , typename Grammar   // = proto::_
+              , typename Super     // = detail::not_a_domain
+            >
+            struct domain
+              : detail::super_domain<Super>
+              , Generator
+            {
+                typedef Generator proto_generator;
+                typedef Grammar proto_grammar;
+
+                /// INTERNAL ONLY
+                typedef void proto_is_domain_;
+            };
+
+            /// \brief The domain expressions have by default, if
+            /// \c proto::extends\<\> has not been used to associate
+            /// a domain with an expression.
+            ///
+            struct default_domain
+              : domain<>
+            {};
+
+            /// \brief A pseudo-domain for use in functions and
+            /// metafunctions that require a domain parameter. It
+            /// indicates that the domain of the parent node should
+            /// be inferred from the domains of the child nodes.
+            ///
+            /// \attention \c deduce_domain is not itself a valid domain.
+            ///
+            struct deduce_domain
+              : domain<detail::not_a_generator, detail::not_a_grammar, detail::not_a_domain>
+            {};
+        }
 
-        /// INTERNAL ONLY
-        ///
-        template<typename T>
-        struct domain_of<T &, void>
+        namespace result_of
         {
-            typedef typename domain_of<T>::type type;
-        };
+            /// A metafunction that returns \c mpl::true_
+            /// if the type \c T is the type of a Proto domain;
+            /// \c mpl::false_ otherwise. If \c T inherits from
+            /// \c proto::domain\<\>, \c is_domain\<T\> is
+            /// \c mpl::true_.
+            template<typename T, typename Void  /* = void*/>
+            struct is_domain
+              : mpl::false_
+            {};
 
-        /// INTERNAL ONLY
-        ///
-        template<typename T>
-        struct domain_of<boost::reference_wrapper<T>, void>
-        {
-            typedef typename domain_of<T>::type type;
-        };
+            /// INTERNAL ONLY
+            ///
+            template<typename T>
+            struct is_domain<T, typename T::proto_is_domain_>
+              : mpl::true_
+            {};
+
+            /// A metafunction that returns the domain of
+            /// a given type. If \c T is a Proto expression
+            /// type, it returns that expression's associated
+            /// domain. If not, it returns
+            /// \c proto::default_domain.
+            template<typename T, typename Void /* = void*/>
+            struct domain_of
+            {
+                typedef default_domain type;
+            };
 
-        /// INTERNAL ONLY
-        ///
-        template<typename T>
-        struct domain_of<boost::reference_wrapper<T> const, void>
-        {
-            typedef typename domain_of<T>::type type;
-        };
-    }
-}}
+            /// INTERNAL ONLY
+            ///
+            template<typename T>
+            struct domain_of<T, typename T::proto_is_expr_>
+            {
+                typedef typename T::proto_domain type;
+            };
+
+            /// INTERNAL ONLY
+            ///
+            template<typename T>
+            struct domain_of<T &, void>
+            {
+                typedef typename domain_of<T>::type type;
+            };
+
+            /// INTERNAL ONLY
+            ///
+            template<typename T>
+            struct domain_of<boost::reference_wrapper<T>, void>
+            {
+                typedef typename domain_of<T>::type type;
+            };
+
+            /// INTERNAL ONLY
+            ///
+            template<typename T>
+            struct domain_of<boost::reference_wrapper<T> const, void>
+            {
+                typedef typename domain_of<T>::type type;
+            };
+        }
+    }}
+
+    #endif
+
+#else
+
+    #define N BOOST_PP_ITERATION()
+
+            template<BOOST_PP_ENUM_PARAMS(BOOST_PROTO_MAX_ARITY, typename T)>
+            struct select_nth<BOOST_PP_DEC(N), BOOST_PP_ENUM_PARAMS(BOOST_PROTO_MAX_ARITY, T)>
+            {
+                typedef BOOST_PP_CAT(T, BOOST_PP_DEC(N)) type;
+            };
+
+            template<BOOST_PP_ENUM_PARAMS(N, typename D)>
+            struct BOOST_PP_CAT(common_domain, N)
+            {
+                #define M0(Z, M, DATA)                                                              \
+                static detail::super_domain<BOOST_PP_CAT(D, M)> & BOOST_PP_CAT(d, M);               \
+                /**/
+                BOOST_PP_REPEAT(N, M0, ~)
+                #undef M0
+
+                enum e
+                {
+                    value0 = 0
+                    #define M0(Z, M, DATA)                                                          \
+                        BOOST_PP_EXPR_IF(M, .test)(BOOST_PP_CAT(d, M))                              \
+                    /**/
+                    #define M1(Z, M, DATA)                                                          \
+                      , BOOST_PP_CAT(value, BOOST_PP_INC(M)) =                                      \
+                        BOOST_PP_CAT(value, M) ?                                                    \
+                        BOOST_PP_CAT(value, M) :                                                    \
+                        sizeof(detail::select_domain<BOOST_PP_CAT(D, M), BOOST_PP_ADD(M, 2)>(       \
+                            BOOST_PP_REPEAT_ ## Z(N, M0, ~).get_super()                             \
+                        )) - 1                                                                      \
+                    /**/
+                    BOOST_PP_REPEAT(N, M1, ~)
+                    #undef M1
+                    #undef M0
+                  , value = BOOST_PP_CAT(value, N) - 1
+                };
+
+                typedef typename select_nth<value BOOST_PP_ENUM_TRAILING_PARAMS(N, D)>::type type;
+                //typedef BOOST_TYPEOF_TPL(d0.test(d1).test(d2).base()) type;
+            };
+
+            template<BOOST_PP_ENUM_PARAMS(N, typename E)>
+            struct BOOST_PP_CAT(deduce_domain, N)
+              : BOOST_PP_CAT(common_domain, N)<
+                    BOOST_PP_ENUM_BINARY_PARAMS(N, typename domain_of<E, >::type BOOST_PP_INTERCEPT)
+                >
+            {};
+
+    #undef N
 
 #endif
Modified: trunk/boost/proto/make_expr.hpp
==============================================================================
--- trunk/boost/proto/make_expr.hpp	(original)
+++ trunk/boost/proto/make_expr.hpp	2010-05-08 18:27:39 EDT (Sat, 08 May 2010)
@@ -91,7 +91,7 @@
     /// INTERNAL ONLY
     ///
     #define BOOST_PROTO_FUSION_NEXT_ITERATOR_TYPE(Z, N, DATA)                                       \
-        typedef typename fusion::result_of::next<                                \
+        typedef typename fusion::result_of::next<                                                   \
             BOOST_PP_CAT(fusion_iterator, N)>::type                                                 \
                 BOOST_PP_CAT(fusion_iterator, BOOST_PP_INC(N));                                     \
         /**/
@@ -100,7 +100,7 @@
     ///
     #define BOOST_PROTO_FUSION_ITERATORS_TYPE(N)                                                    \
         typedef                                                                                     \
-            typename fusion::result_of::begin<Sequence const>::type              \
+            typename fusion::result_of::begin<Sequence const>::type                                 \
         fusion_iterator0;                                                                           \
         BOOST_PP_REPEAT(BOOST_PP_DEC(N), BOOST_PROTO_FUSION_NEXT_ITERATOR_TYPE, fusion_iterator)    \
         /**/
@@ -109,7 +109,7 @@
     ///
     #define BOOST_PROTO_FUSION_AT_TYPE(Z, N, DATA)                                                  \
         typename add_const<                                                                         \
-            typename fusion::result_of::value_of<                                \
+            typename fusion::result_of::value_of<                                                   \
                 BOOST_PP_CAT(fusion_iterator, N)                                                    \
             >::type                                                                                 \
         >::type                                                                                     \
@@ -193,47 +193,6 @@
                 }
             };
 
-            template<
-                int Index
-                BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(
-                    BOOST_PROTO_MAX_ARITY
-                  , typename D
-                  , = void BOOST_PP_INTERCEPT
-                )
-            >
-            struct select_nth
-            {
-                BOOST_MPL_ASSERT_MSG((false), PROTO_DOMAIN_MISMATCH, (select_nth));
-                typedef default_domain type;
-            };
-
-            template<typename Void = void>
-            struct deduce_domain0
-            {
-                typedef default_domain type;
-            };
-
-            template<int I>
-            struct sized
-            {
-                char buffer[I];
-            };
-
-            template<typename T>
-            struct nondeduced_domain
-            {
-                typedef nondeduced_domain type;
-                nondeduced_domain(T);
-                nondeduced_domain(default_domain);
-            };
-
-            template<>
-            struct nondeduced_domain<default_domain>
-            {
-                typedef nondeduced_domain type;
-                nondeduced_domain(default_domain);
-            };
-
             template<typename Tag, typename Domain, typename Sequence, std::size_t Size>
             struct unpack_expr_
             {};
@@ -899,59 +858,6 @@
         };
     #endif
 
-        template<BOOST_PP_ENUM_PARAMS(BOOST_PROTO_MAX_ARITY, typename T)>
-        struct select_nth<BOOST_PP_DEC(N), BOOST_PP_ENUM_PARAMS(BOOST_PROTO_MAX_ARITY, T)>
-        {
-            typedef BOOST_PP_CAT(T, BOOST_PP_DEC(N)) type;
-        };
-
-        // Use function overloading as an efficient mechanism for
-        // calculating the domain shared by a bunch of proto expressions
-        // (or non-expressions, assumed to be in the default_domain).
-        // The domain of a set of domains S is deduced as follows:
-        // - If S contains only default_domain, the deduced domain is
-        //   default_domain.
-        // - If S contains only X and default_domain, the deduced domain
-        //   is X.
-        // - If S contains different domains X and Y, neither of which is
-        //   default_domain, it is an error.
-        template<BOOST_PP_ENUM_PARAMS(N, typename A)>
-        struct BOOST_PP_CAT(deduce_domain, N)
-        {
-            #if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
-            // The function overloading trick doesn't work on MSVC-7.1, so
-            // do it the hard (expensive) way.
-            typedef
-                typename mpl::eval_if_c<
-                    is_same<typename domain_of<A0>::type, default_domain>::value
-                  , BOOST_PP_CAT(deduce_domain, BOOST_PP_DEC(N))<BOOST_PP_ENUM_SHIFTED_PARAMS(N, A)>
-                  , domain_of<A0>
-                >::type
-            type;
-            #else
-            #define M0(N, F) char (&F)[BOOST_PP_INC(N)]
-            static M0(BOOST_PROTO_MAX_ARITY, deducer(...));
-            #define M1(Z, X, DATA)                                                                  \
-            typedef typename domain_of<BOOST_PP_CAT(A, X)>::type BOOST_PP_CAT(D, X);                \
-            static BOOST_PP_CAT(D, X) &BOOST_PP_CAT(d, X);                                          \
-            template<typename T>                                                                    \
-            static M0(X, deducer(                                                                   \
-                BOOST_PP_ENUM_PARAMS_Z(Z, X, default_domain BOOST_PP_INTERCEPT)                     \
-                BOOST_PP_COMMA_IF(X) T                                                              \
-                BOOST_PP_ENUM_TRAILING_PARAMS_Z(                                                    \
-                    Z                                                                               \
-                  , BOOST_PP_DEC(BOOST_PP_SUB(N, X))                                                \
-                  , typename nondeduced_domain<T>::type BOOST_PP_INTERCEPT                          \
-                )                                                                                   \
-            ));
-            BOOST_PP_REPEAT(N, M1, ~)
-            #undef M0
-            #undef M1
-            BOOST_STATIC_CONSTANT(int, value = sizeof(deducer(BOOST_PP_ENUM_PARAMS(N, d))) - 1);
-            typedef typename select_nth<value, BOOST_PP_ENUM_PARAMS(N, D)>::type type;
-            #endif
-        };
-
         template<typename Tag, typename Domain BOOST_PP_ENUM_TRAILING_PARAMS(N, typename A)>
         struct make_expr_<Tag, Domain BOOST_PP_ENUM_TRAILING_PARAMS(N, A)
             BOOST_PP_ENUM_TRAILING_PARAMS(M, void BOOST_PP_INTERCEPT), void>
Modified: trunk/boost/proto/operators.hpp
==============================================================================
--- trunk/boost/proto/operators.hpp	(original)
+++ trunk/boost/proto/operators.hpp	2010-05-08 18:27:39 EDT (Sat, 08 May 2010)
@@ -18,6 +18,7 @@
 #include <boost/proto/proto_fwd.hpp>
 #include <boost/proto/tags.hpp>
 #include <boost/proto/expr.hpp>
+#include <boost/proto/domain.hpp>
 #include <boost/proto/matches.hpp>
 #include <boost/proto/generate.hpp>
 #include <boost/proto/make_expr.hpp>
@@ -26,31 +27,6 @@
 {
     namespace detail
     {
-        template<typename Domain1, typename Domain2>
-        struct choose_domain2
-        {
-            BOOST_MPL_ASSERT((boost::is_same<Domain1, Domain2>));
-            typedef Domain1 type;
-        };
-
-        template<typename Domain1>
-        struct choose_domain2<Domain1, proto::default_domain>
-        {
-            typedef Domain1 type;
-        };
-
-        template<typename Domain2>
-        struct choose_domain2<proto::default_domain, Domain2>
-        {
-            typedef Domain2 type;
-        };
-
-        template<>
-        struct choose_domain2<proto::default_domain, proto::default_domain>
-        {
-            typedef proto::default_domain type;
-        };
-
         template<typename Domain, typename Expr, typename EnableIf = void>
         struct generate_if
           : lazy_enable_if_c<
@@ -156,12 +132,12 @@
         template<typename Tag, typename Left, typename Right>
         struct as_expr_if<Tag, Left, Right, typename Left::proto_is_expr_, typename Right::proto_is_expr_>
           : generate_if<
-                typename choose_domain2<typename Left::proto_domain, typename Right::proto_domain>::type
+                typename common_domain2<typename Left::proto_domain, typename Right::proto_domain>::type
               , proto::expr<Tag, list2<Left &, Right &>, 2>
             >
         {
             typedef proto::expr<Tag, list2<Left &, Right &>, 2> expr_type;
-            typedef typename choose_domain2<typename Left::proto_domain, typename Right::proto_domain>::type proto_domain;
+            typedef typename common_domain2<typename Left::proto_domain, typename Right::proto_domain>::type proto_domain;
 
             static typename proto_domain::template result<proto_domain(expr_type)>::type
             make(Left &left, Right &right)
Modified: trunk/boost/proto/proto_fwd.hpp
==============================================================================
--- trunk/boost/proto/proto_fwd.hpp	(original)
+++ trunk/boost/proto/proto_fwd.hpp	2010-05-08 18:27:39 EDT (Sat, 08 May 2010)
@@ -138,6 +138,10 @@
             typename boost::remove_const<typename boost::remove_reference<X>::type>::type
 
         struct _default;
+
+        struct not_a_domain;
+        struct not_a_grammar;
+        struct not_a_generator;
     }
 
     typedef detail::ignore const ignore;
@@ -255,7 +259,11 @@
     ////////////////////////////////////////////////////////////////////////////////////////////////
     namespace domainns_
     {
-        template<typename Generator = default_generator, typename Grammar = proto::_>
+        template<
+            typename Generator  = default_generator
+          , typename Grammar    = proto::_
+          , typename Super      = detail::not_a_domain
+        >
         struct domain;
 
         struct default_domain;
Modified: trunk/boost/proto/proto_typeof.hpp
==============================================================================
--- trunk/boost/proto/proto_typeof.hpp	(original)
+++ trunk/boost/proto/proto_typeof.hpp	2010-05-08 18:27:39 EDT (Sat, 08 May 2010)
@@ -67,6 +67,11 @@
 BOOST_TYPEOF_REGISTER_TEMPLATE(boost::proto::exprns_::expr, (typename)(typename)(long))
 BOOST_TYPEOF_REGISTER_TEMPLATE(boost::proto::utility::literal, (typename)(typename))
 
+BOOST_TYPEOF_REGISTER_TYPE(boost::proto::detail::not_a_generator)
+BOOST_TYPEOF_REGISTER_TYPE(boost::proto::detail::not_a_grammar)
+BOOST_TYPEOF_REGISTER_TYPE(boost::proto::detail::not_a_domain)
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::proto::domainns_::domain, 3)
+
 BOOST_TYPEOF_REGISTER_TEMPLATE(boost::proto::argsns_::term, 1)
 BOOST_TYPEOF_REGISTER_TEMPLATE(boost::proto::argsns_::list1, 1)
 BOOST_TYPEOF_REGISTER_TEMPLATE(boost::proto::argsns_::list2, 2)