Boost logo

Boost-Commit :

From: eric_at_[hidden]
Date: 2008-01-30 17:10:14


Author: eric_niebler
Date: 2008-01-30 17:10:13 EST (Wed, 30 Jan 2008)
New Revision: 43023
URL: http://svn.boost.org/trac/boost/changeset/43023

Log:
finally, a make_expr() I can live with
Text files modified:
   trunk/boost/xpressive/proto/domain.hpp | 24 +++
   trunk/boost/xpressive/proto/make_expr.hpp | 309 ++++++++++++++++++---------------------
   trunk/boost/xpressive/proto/operators.hpp | 24 +-
   trunk/boost/xpressive/proto/proto_fwd.hpp | 114 ++-----------
   trunk/boost/xpressive/proto/transform/arg.hpp | 36 ++++
   trunk/boost/xpressive/regex_primitives.hpp | 98 +++++++++---
   trunk/libs/xpressive/proto/doc/preface.qbk | 11 +
   trunk/libs/xpressive/proto/example/mixed.cpp | 5
   trunk/libs/xpressive/proto/test/make_expr.cpp | 185 ++++++++++++++++++-----
   9 files changed, 461 insertions(+), 345 deletions(-)

Modified: trunk/boost/xpressive/proto/domain.hpp
==============================================================================
--- trunk/boost/xpressive/proto/domain.hpp (original)
+++ trunk/boost/xpressive/proto/domain.hpp 2008-01-30 17:10:13 EST (Wed, 30 Jan 2008)
@@ -142,6 +142,30 @@
         {
             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;
+ };
     }
 }}
 

Modified: trunk/boost/xpressive/proto/make_expr.hpp
==============================================================================
--- trunk/boost/xpressive/proto/make_expr.hpp (original)
+++ trunk/boost/xpressive/proto/make_expr.hpp 2008-01-30 17:10:13 EST (Wed, 30 Jan 2008)
@@ -47,6 +47,8 @@
     #include <boost/preprocessor/seq/push_front.hpp>
     #include <boost/preprocessor/list/for_each_i.hpp>
     #include <boost/ref.hpp>
+ #include <boost/mpl/if.hpp>
+ #include <boost/mpl/eval_if.hpp>
     #include <boost/mpl/apply_wrap.hpp>
     #include <boost/utility/enable_if.hpp>
     #include <boost/type_traits/is_same.hpp>
@@ -79,29 +81,28 @@
     /// INTERNAL ONLY
     ///
     #define BOOST_PROTO_AS_ARG_TYPE(Z, N, DATA) \
- typename boost::proto::result_of::as_arg< \
- BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(2, 0, DATA), N) \
- , BOOST_PP_TUPLE_ELEM(2, 1, DATA) \
+ typename boost::proto::detail::protoify_< \
+ BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(3, 0, DATA), N) \
+ , BOOST_PP_TUPLE_ELEM(3, 2, DATA) \
>::type \
         /**/
 
     /// INTERNAL ONLY
     ///
     #define BOOST_PROTO_AS_ARG(Z, N, DATA) \
- boost::proto::as_arg<BOOST_PP_TUPLE_ELEM(2, 1, DATA) >( \
- BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(2, 0, DATA), N) \
- ) \
+ boost::proto::detail::protoify_< \
+ BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(3, 0, DATA), N) \
+ , BOOST_PP_TUPLE_ELEM(3, 2, DATA) \
+ >::call(BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(3, 1, DATA), N)) \
         /**/
 
     /// INTERNAL ONLY
     ///
     # define BOOST_PROTO_AT_TYPE(Z, N, DATA) \
- typename remove_reference< \
- typename add_const< \
- typename fusion::BOOST_PROTO_FUSION_RESULT_OF::value_at_c< \
- BOOST_PP_TUPLE_ELEM(2, 0, DATA) \
- , N \
- >::type \
+ typename add_const< \
+ typename fusion::BOOST_PROTO_FUSION_RESULT_OF::value_at_c< \
+ BOOST_PP_TUPLE_ELEM(3, 0, DATA) \
+ , N \
>::type \
>::type \
         /**/
@@ -109,24 +110,25 @@
     /// INTERNAL ONLY
     ///
     # define BOOST_PROTO_AT(Z, N, DATA) \
- fusion::BOOST_PROTO_FUSION_AT_C(N, BOOST_PP_TUPLE_ELEM(2, 0, DATA)) \
+ fusion::BOOST_PROTO_FUSION_AT_C(N, BOOST_PP_TUPLE_ELEM(3, 1, DATA)) \
         /**/
 
     /// INTERNAL ONLY
     ///
     #define BOOST_PROTO_AS_ARG_AT_TYPE(Z, N, DATA) \
- typename boost::proto::result_of::as_arg< \
+ typename boost::proto::detail::protoify_< \
             BOOST_PROTO_AT_TYPE(Z, N, DATA) \
- , BOOST_PP_TUPLE_ELEM(2, 1, DATA) \
+ , BOOST_PP_TUPLE_ELEM(3, 2, DATA) \
>::type \
         /**/
 
     /// INTERNAL ONLY
     ///
     #define BOOST_PROTO_AS_ARG_AT(Z, N, DATA) \
- boost::proto::as_arg<BOOST_PP_TUPLE_ELEM(2, 1, DATA) >( \
- BOOST_PROTO_AT(Z, N, DATA) \
- ) \
+ boost::proto::detail::protoify_< \
+ BOOST_PROTO_AT_TYPE(Z, N, DATA) \
+ , BOOST_PP_TUPLE_ELEM(3, 2, DATA) \
+ >::call(BOOST_PROTO_AT(Z, N, DATA)) \
         /**/
 
     /// INTERNAL ONLY
@@ -210,14 +212,14 @@
     #define BOOST_PROTO_VARARG_AS_EXPR_(R, DATA, I, ELEM) \
         BOOST_PP_EXPR_IF( \
             BOOST_PP_GREATER(I, 1) \
- , ((boost::proto::utility::static_< \
+ , (( \
                 BOOST_PP_SEQ_HEAD(ELEM) \
                 BOOST_PP_IF( \
                     BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(ELEM)) \
                   , BOOST_PROTO_TEMPLATE_PARAMS_YES_ \
                   , BOOST_PROTO_TEMPLATE_PARAMS_NO_ \
- )(R, DATA, I, ELEM) \
- >::value)) \
+ )(R, DATA, I, ELEM)() \
+ )) \
         ) \
         /**/
 
@@ -268,13 +270,9 @@
                   , BOOST_PP_TUPLE_ELEM(4, 1, DATA) \
                 ) \
             ) \
- BOOST_PP_ENUM_TRAILING_BINARY_PARAMS( \
- N \
- , typename boost::proto::utility::remref<const A \
- , >::type BOOST_PP_INTERCEPT \
- ) \
+ BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(Z, N, A, const & BOOST_PP_INTERCEPT) \
>::type const \
- BOOST_PP_TUPLE_ELEM(4, 0, DATA)(BOOST_PP_ENUM_BINARY_PARAMS_Z(Z, N, const A, &a)) \
+ BOOST_PP_TUPLE_ELEM(4, 0, DATA)(BOOST_PP_ENUM_BINARY_PARAMS_Z(Z, N, A, const &a)) \
         { \
             return boost::proto::detail::make_expr_< \
                 BOOST_PP_SEQ_FOR_EACH_I( \
@@ -287,11 +285,7 @@
                       , BOOST_PP_TUPLE_ELEM(4, 1, DATA) \
                     ) \
                 ) \
- BOOST_PP_ENUM_TRAILING_BINARY_PARAMS( \
- N \
- , typename boost::proto::utility::remref<const A \
- , >::type BOOST_PP_INTERCEPT \
- ) \
+ BOOST_PP_ENUM_TRAILING_BINARY_PARAMS_Z(Z, N, A, const & BOOST_PP_INTERCEPT) \
>::call( \
                 BOOST_PP_SEQ_ENUM( \
                     BOOST_PP_SEQ_FOR_EACH_I( \
@@ -347,49 +341,56 @@
         namespace utility
         {
             template<typename T>
- struct addref
+ struct static_
             {
- typedef
- typename boost::unwrap_reference<T>::type &
- type;
+ static T const value;
             };
 
             template<typename T>
- struct addref<T &>
- {
- typedef
- typename boost::unwrap_reference<T>::type &
- type;
- };
+ T const static_<T>::value = T();
+ }
 
- template<typename T>
- struct remref
+ namespace detail
+ {
+ template<typename T, typename Domain>
+ struct protoify_
             {
                 typedef
- typename boost::unwrap_reference<T>::type
+ typename mpl::eval_if<
+ boost::is_reference_wrapper<T>
+ , proto::result_of::as_arg<typename boost::unwrap_reference<T>::type, Domain>
+ , proto::result_of::as_expr<T, Domain>
+ >::type
                 type;
+
+ static type call(T &t)
+ {
+ return typename mpl::if_<
+ is_reference_wrapper<T>
+ , functional::as_arg<Domain>
+ , functional::as_expr<Domain>
+ >::type()(static_cast<typename boost::unwrap_reference<T>::type &>(t));
+ }
             };
 
- template<typename T>
- struct remref<T &>
+ template<typename T, typename Domain>
+ struct protoify_<T &, Domain>
             {
                 typedef
- typename boost::unwrap_reference<T>::type
+ typename proto::result_of::as_arg<
+ typename boost::unwrap_reference<T>::type
+ , Domain
+ >::type
                 type;
- };
 
- template<typename T>
- struct static_
- {
- static T const value;
+ static type call(T &t)
+ {
+ return functional::as_arg<Domain>()(
+ static_cast<typename boost::unwrap_reference<T>::type &>(t)
+ );
+ }
             };
 
- template<typename T>
- T const static_<T>::value = T();
- }
-
- namespace detail
- {
             template<
                 typename Domain
                 BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(
@@ -427,26 +428,25 @@
             template<typename Domain, typename Sequence>
             struct unpack_expr_<tag::terminal, Domain, Sequence, 1u>
             {
- typedef proto::expr<
- tag::terminal
- , args0<
- typename add_reference<
- typename add_const<
- typename fusion::BOOST_PROTO_FUSION_RESULT_OF::value_at_c<
- Sequence
- , 0
- >::type
- >::type
+ typedef
+ typename add_const<
+ typename fusion::BOOST_PROTO_FUSION_RESULT_OF::value_at_c<
+ Sequence
+ , 0
>::type
- >
- > expr_type;
+ >::type
+ terminal_type;
 
- typedef typename Domain::template apply<expr_type>::type type;
+ typedef
+ typename proto::detail::protoify_<
+ terminal_type
+ , Domain
+ >::type
+ type;
 
                 static type const call(Sequence const &sequence)
                 {
- expr_type that = {fusion::BOOST_PROTO_FUSION_AT_C(0, sequence)};
- return Domain::make(that);
+ return proto::detail::protoify_<terminal_type, Domain>::call(fusion::BOOST_PROTO_FUSION_AT_C(0, sequence));
                 }
             };
 
@@ -472,14 +472,11 @@
             struct make_expr_<tag::terminal, Domain, A
                 BOOST_PP_ENUM_TRAILING_PARAMS(BOOST_PROTO_MAX_ARITY, void BOOST_PP_INTERCEPT)>
             {
- typedef typename utility::addref<A>::type reference;
- typedef proto::expr<tag::terminal, args0<reference> > expr_type;
- typedef typename Domain::template apply<expr_type>::type type;
+ typedef typename proto::detail::protoify_<A, Domain>::type type;
 
- static type const call(reference a)
+ static type const call(typename add_reference<A>::type a)
                 {
- expr_type that = {a};
- return Domain::make(that);
+ return proto::detail::protoify_<A, Domain>::call(a);
                 }
             };
 
@@ -579,14 +576,14 @@
                 typename result_of::make_expr<
                     Tag
                   , Domain
- , typename utility::remref<A0>::type
+ , A0
>::type const
                 operator ()(A0 &a0 BOOST_PROTO_DISABLE_IF_IS_CONST(A0)) const
                 {
                     return proto::detail::make_expr_<
                         Tag
                       , Domain
- , typename utility::remref<A0>::type
+ , A0
>::call(a0);
                 }
 
@@ -596,16 +593,16 @@
                 typename result_of::make_expr<
                     Tag
                   , Domain
- , typename utility::remref<A0>::type
- , typename utility::remref<A1>::type
+ , A0
+ , A1
>::type const
                 operator ()(A0 &a0, A1 &a1 BOOST_PROTO_DISABLE_IF_IS_CONST(A0) BOOST_PROTO_DISABLE_IF_IS_CONST(A1)) const
                 {
                     return proto::detail::make_expr_<
                         Tag
                       , Domain
- , typename utility::remref<A0>::type
- , typename utility::remref<A1>::type
+ , A0
+ , A1
>::call(a0, a1);
                 }
 
@@ -615,16 +612,16 @@
                 typename result_of::make_expr<
                     Tag
                   , Domain
- , typename utility::remref<A0>::type
- , typename utility::remref<A1 const>::type
+ , A0
+ , A1 const
>::type const
                 operator ()(A0 &a0, A1 const &a1 BOOST_PROTO_DISABLE_IF_IS_CONST(A0)) const
                 {
                     return proto::detail::make_expr_<
                         Tag
                       , Domain
- , typename utility::remref<A0>::type
- , typename utility::remref<A1 const>::type
+ , A0
+ , A1 const
>::call(a0, a1);
                 }
 
@@ -634,16 +631,16 @@
                 typename result_of::make_expr<
                     Tag
                   , Domain
- , typename utility::remref<A0 const>::type
- , typename utility::remref<A1>::type
+ , A0 const
+ , A1
>::type const
                 operator ()(A0 const &a0, A1 &a1 BOOST_PROTO_DISABLE_IF_IS_CONST(A1)) const
                 {
                     return proto::detail::make_expr_<
                         Tag
                       , Domain
- , typename utility::remref<A0 const>::type
- , typename utility::remref<A1>::type
+ , A0 const
+ , A1
>::call(a0, a1);
                 }
 
@@ -670,7 +667,7 @@
                         typename result_of::make_expr<
                             tag::terminal
                           , Domain
- , typename utility::remref<A>::type
+ , typename remove_reference<A>::type
>::type
                     type;
                 };
@@ -679,14 +676,14 @@
                 typename result_of::make_expr<
                     tag::terminal
                   , Domain
- , typename utility::remref<A>::type
+ , A
>::type const
                 operator ()(A &a BOOST_PROTO_DISABLE_IF_IS_CONST(A)) const
                 {
                     return proto::detail::make_expr_<
                         tag::terminal
                       , Domain
- , typename utility::remref<A>::type
+ , A
>::call(a);
                 }
 
@@ -694,14 +691,14 @@
                 typename result_of::make_expr<
                     tag::terminal
                   , Domain
- , typename utility::remref<A const>::type
+ , A const
>::type const
                 operator ()(A const &a) const
                 {
                     return proto::detail::make_expr_<
                         tag::terminal
                       , Domain
- , typename utility::remref<A const>::type
+ , A const
>::call(a);
                 }
             };
@@ -874,7 +871,7 @@
             is_domain<A0>
           , result_of::make_expr<
                 Tag
- , typename utility::remref<A0>::type
+ , A0
>
>::type const
         make_expr(A0 &a0 BOOST_PROTO_DISABLE_IF_IS_CONST(A0))
@@ -882,19 +879,19 @@
             return proto::detail::make_expr_<
                 Tag
               , deduce_domain
- , typename utility::remref<A0>::type
+ , A0
>::call(a0);
         }
 
- /// \ovoerload
+ /// \overload
         ///
         template<typename Tag, typename A0, typename A1>
         typename lazy_disable_if<
             is_domain<A0>
           , result_of::make_expr<
                 Tag
- , typename utility::remref<A0>::type
- , typename utility::remref<A1>::type
+ , A0
+ , A1
>
>::type const
         make_expr(A0 &a0, A1 &a1 BOOST_PROTO_DISABLE_IF_IS_CONST(A0) BOOST_PROTO_DISABLE_IF_IS_CONST(A1))
@@ -902,20 +899,20 @@
             return proto::detail::make_expr_<
                 Tag
               , deduce_domain
- , typename utility::remref<A0>::type
- , typename utility::remref<A1>::type
+ , A0
+ , A1
>::call(a0, a1);
         }
 
- /// \ovoerload
+ /// \overload
         ///
         template<typename Tag, typename A0, typename A1>
         typename lazy_disable_if<
             is_domain<A0>
           , result_of::make_expr<
                 Tag
- , typename utility::remref<A0>::type
- , typename utility::remref<A1 const>::type
+ , A0
+ , A1 const
>
>::type const
         make_expr(A0 &a0, A1 const &a1 BOOST_PROTO_DISABLE_IF_IS_CONST(A0))
@@ -923,20 +920,20 @@
             return proto::detail::make_expr_<
                 Tag
               , deduce_domain
- , typename utility::remref<A0>::type
- , typename utility::remref<A1 const>::type
+ , A0
+ , A1 const
>::call(a0, a1);
         }
 
- /// \ovoerload
+ /// \overload
         ///
         template<typename Tag, typename A0, typename A1>
         typename lazy_disable_if<
             is_domain<A0>
           , result_of::make_expr<
                 Tag
- , typename utility::remref<A0 const>::type
- , typename utility::remref<A1>::type
+ , A0 const
+ , A1
>
>::type const
         make_expr(A0 const &a0, A1 &a1 BOOST_PROTO_DISABLE_IF_IS_CONST(A1))
@@ -944,8 +941,8 @@
             return proto::detail::make_expr_<
                 Tag
               , deduce_domain
- , typename utility::remref<A0 const>::type
- , typename utility::remref<A1>::type
+ , A0 const
+ , A1
>::call(a0, a1);
         }
 
@@ -955,14 +952,14 @@
         typename result_of::make_expr<
             Tag
           , Domain
- , typename utility::remref<B0>::type
+ , B0
>::type const
         make_expr(B0 &b0 BOOST_PROTO_DISABLE_IF_IS_CONST(B0))
         {
             return proto::detail::make_expr_<
                 Tag
               , Domain
- , typename utility::remref<B0>::type
+ , B0
>::call(b0);
         }
 
@@ -972,16 +969,16 @@
         typename result_of::make_expr<
             Tag
           , Domain
- , typename utility::remref<B0>::type
- , typename utility::remref<B1>::type
+ , B0
+ , B1
>::type const
         make_expr(B0 &b0, B1 &b1 BOOST_PROTO_DISABLE_IF_IS_CONST(B0) BOOST_PROTO_DISABLE_IF_IS_CONST(B1))
         {
             return proto::detail::make_expr_<
                 Tag
               , Domain
- , typename utility::remref<B0>::type
- , typename utility::remref<B1>::type
+ , B0
+ , B1
>::call(b0, b1);
         }
 
@@ -991,16 +988,16 @@
         typename result_of::make_expr<
             Tag
           , Domain
- , typename utility::remref<B0>::type
- , typename utility::remref<B1 const>::type
+ , B0
+ , B1 const
>::type const
         make_expr(B0 &b0, B1 const &b1 BOOST_PROTO_DISABLE_IF_IS_CONST(B0))
         {
             return proto::detail::make_expr_<
                 Tag
               , Domain
- , typename utility::remref<B0>::type
- , typename utility::remref<B1 const>::type
+ , B0
+ , B1 const
>::call(b0, b1);
         }
 
@@ -1010,16 +1007,16 @@
         typename result_of::make_expr<
             Tag
           , Domain
- , typename utility::remref<B0 const>::type
- , typename utility::remref<B1>::type
+ , B0 const
+ , B1
>::type const
         make_expr(B0 const &b0, B1 &b1 BOOST_PROTO_DISABLE_IF_IS_CONST(B1))
         {
             return proto::detail::make_expr_<
                 Tag
               , Domain
- , typename utility::remref<B0 const>::type
- , typename utility::remref<B1>::type
+ , B0 const
+ , B1
>::call(b0, b1);
         }
 
@@ -1064,15 +1061,15 @@
         {
             typedef proto::expr<
                 Tag
- , BOOST_PP_CAT(args, N)<BOOST_PP_ENUM(N, BOOST_PROTO_AS_ARG_TYPE, (A, Domain)) >
+ , BOOST_PP_CAT(args, N)<BOOST_PP_ENUM(N, BOOST_PROTO_AS_ARG_TYPE, (A, ~, Domain)) >
> expr_type;
 
             typedef typename Domain::template apply<expr_type>::type type;
 
- static type const call(BOOST_PP_ENUM_BINARY_PARAMS(N, A, &a))
+ static type const call(BOOST_PP_ENUM_BINARY_PARAMS(N, typename add_reference<A, >::type a))
             {
                 expr_type that = {
- BOOST_PP_ENUM(N, BOOST_PROTO_AS_ARG, (a, Domain))
+ BOOST_PP_ENUM(N, BOOST_PROTO_AS_ARG, (A, a, Domain))
                 };
                 return Domain::make(that);
             }
@@ -1100,7 +1097,7 @@
             typedef proto::expr<
                 Tag
               , BOOST_PP_CAT(args, N)<
- BOOST_PP_ENUM(N, BOOST_PROTO_AS_ARG_AT_TYPE, (Sequence, Domain))
+ BOOST_PP_ENUM(N, BOOST_PROTO_AS_ARG_AT_TYPE, (Sequence const, ~, Domain))
>
> expr_type;
 
@@ -1109,7 +1106,7 @@
             static type const call(Sequence const &sequence)
             {
                 expr_type that = {
- BOOST_PP_ENUM(N, BOOST_PROTO_AS_ARG_AT, (sequence, Domain))
+ BOOST_PP_ENUM(N, BOOST_PROTO_AS_ARG_AT, (Sequence const, sequence, Domain))
                 };
                 return Domain::make(that);
             }
@@ -1121,10 +1118,10 @@
                 Tag
               , typename detail::deduce_domain_<
                     typename domain_of<
- BOOST_PROTO_AT_TYPE(~, 0, (Sequence const, ~))
+ BOOST_PROTO_AT_TYPE(~, 0, (Sequence const, ~, ~))
>::type
                     BOOST_PP_COMMA_IF(BOOST_PP_DEC(N))
- BOOST_PP_ENUM_SHIFTED(N, BOOST_PROTO_AT_TYPE, (Sequence const, ~))
+ BOOST_PP_ENUM_SHIFTED(N, BOOST_PROTO_AT_TYPE, (Sequence const, ~, ~))
>::type
               , Sequence
               , N
@@ -1147,7 +1144,7 @@
                   , Domain
                     BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(
                         N
- , typename utility::remref<A
+ , typename remove_reference<A
                       , >::type BOOST_PP_INTERCEPT
                     )
>::type
@@ -1160,22 +1157,14 @@
         typename result_of::make_expr<
             Tag
           , Domain
- BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(
- N
- , typename utility::remref<const A
- , >::type BOOST_PP_INTERCEPT
- )
+ BOOST_PP_ENUM_TRAILING_PARAMS(N, const A)
>::type const
         operator ()(BOOST_PP_ENUM_BINARY_PARAMS(N, const A, &a)) const
         {
             return proto::detail::make_expr_<
                 Tag
               , Domain
- BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(
- N
- , typename utility::remref<const A
- , >::type BOOST_PP_INTERCEPT
- )
+ BOOST_PP_ENUM_TRAILING_PARAMS(N, const A)
>::call(BOOST_PP_ENUM_PARAMS(N, a));
         }
 
@@ -1192,11 +1181,7 @@
             is_domain<A0>
           , result_of::make_expr<
                 Tag
- BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(
- N
- , typename utility::remref<const A
- , >::type BOOST_PP_INTERCEPT
- )
+ BOOST_PP_ENUM_TRAILING_PARAMS(N, const A)
>
>::type const
         make_expr(BOOST_PP_ENUM_BINARY_PARAMS(N, const A, &a))
@@ -1204,11 +1189,7 @@
             return proto::detail::make_expr_<
                 Tag
               , deduce_domain
- BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(
- N
- , typename utility::remref<const A
- , >::type BOOST_PP_INTERCEPT
- )
+ BOOST_PP_ENUM_TRAILING_PARAMS(N, const A)
>::call(BOOST_PP_ENUM_PARAMS(N, a));
         }
 
@@ -1218,22 +1199,14 @@
         typename result_of::make_expr<
             Tag
           , Domain
- BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(
- N
- , typename utility::remref<const B
- , >::type BOOST_PP_INTERCEPT
- )
+ BOOST_PP_ENUM_TRAILING_PARAMS(N, const B)
>::type const
         make_expr(BOOST_PP_ENUM_BINARY_PARAMS(N, const B, &b))
         {
             return proto::detail::make_expr_<
                 Tag
               , Domain
- BOOST_PP_ENUM_TRAILING_BINARY_PARAMS(
- N
- , typename utility::remref<const B
- , >::type BOOST_PP_INTERCEPT
- )
+ BOOST_PP_ENUM_TRAILING_PARAMS(N, const B)
>::call(BOOST_PP_ENUM_PARAMS(N, b));
         }
 

Modified: trunk/boost/xpressive/proto/operators.hpp
==============================================================================
--- trunk/boost/xpressive/proto/operators.hpp (original)
+++ trunk/boost/xpressive/proto/operators.hpp 2008-01-30 17:10:13 EST (Wed, 30 Jan 2008)
@@ -291,54 +291,54 @@
 #define BOOST_PROTO_DEFINE_UNARY_OPERATOR(OP, TAG, TRAIT, DOMAIN, POST) \
     template<typename Arg> \
     typename boost::proto::detail::enable_unary<DOMAIN, TRAIT<Arg>, Arg \
- , typename boost::proto::result_of::make_expr<TAG, DOMAIN, Arg>::type \
+ , typename boost::proto::result_of::make_expr<TAG, DOMAIN, Arg &>::type \
>::type const \
     operator OP(Arg &arg BOOST_PROTO_UNARY_OP_IS_POSTFIX_ ## POST) \
     { \
- return boost::proto::make_expr<TAG, DOMAIN>(arg); \
+ return boost::proto::make_expr<TAG, DOMAIN>(boost::ref(arg)); \
     } \
     template<typename Arg> \
     typename boost::proto::detail::enable_unary<DOMAIN, TRAIT<Arg>, Arg \
- , typename boost::proto::result_of::make_expr<TAG, DOMAIN, Arg const>::type \
+ , typename boost::proto::result_of::make_expr<TAG, DOMAIN, Arg const &>::type \
>::type const \
     operator OP(Arg const &arg BOOST_PROTO_UNARY_OP_IS_POSTFIX_ ## POST) \
     { \
- return boost::proto::make_expr<TAG, DOMAIN>(arg); \
+ return boost::proto::make_expr<TAG, DOMAIN>(boost::ref(arg)); \
     } \
     /**/
 
 #define BOOST_PROTO_DEFINE_BINARY_OPERATOR(OP, TAG, TRAIT, DOMAIN) \
     template<typename Left, typename Right> \
     typename boost::proto::detail::enable_binary<DOMAIN, TRAIT<Left>, Left, TRAIT<Right>, Right \
- , typename boost::proto::result_of::make_expr<TAG, DOMAIN, Left, Right>::type \
+ , typename boost::proto::result_of::make_expr<TAG, DOMAIN, Left &, Right &>::type \
>::type const \
     operator OP(Left &left, Right &right) \
     { \
- return boost::proto::make_expr<TAG, DOMAIN>(left, right); \
+ return boost::proto::make_expr<TAG, DOMAIN>(boost::ref(left), boost::ref(right)); \
     } \
     template<typename Left, typename Right> \
     typename boost::proto::detail::enable_binary<DOMAIN, TRAIT<Left>, Left, TRAIT<Right>, Right \
- , typename boost::proto::result_of::make_expr<TAG, DOMAIN, Left, Right const>::type \
+ , typename boost::proto::result_of::make_expr<TAG, DOMAIN, Left &, Right const &>::type \
>::type const \
     operator OP(Left &left, Right const &right) \
     { \
- return boost::proto::make_expr<TAG, DOMAIN>(left, right); \
+ return boost::proto::make_expr<TAG, DOMAIN>(boost::ref(left), boost::ref(right)); \
     } \
     template<typename Left, typename Right> \
     typename boost::proto::detail::enable_binary<DOMAIN, TRAIT<Left>, Left, TRAIT<Right>, Right \
- , typename boost::proto::result_of::make_expr<TAG, DOMAIN, Left const, Right>::type \
+ , typename boost::proto::result_of::make_expr<TAG, DOMAIN, Left const &, Right &>::type \
>::type const \
     operator OP(Left const &left, Right &right) \
     { \
- return boost::proto::make_expr<TAG, DOMAIN>(left, right); \
+ return boost::proto::make_expr<TAG, DOMAIN>(boost::ref(left), boost::ref(right)); \
     } \
     template<typename Left, typename Right> \
     typename boost::proto::detail::enable_binary<DOMAIN, TRAIT<Left>, Left, TRAIT<Right>, Right \
- , typename boost::proto::result_of::make_expr<TAG, DOMAIN, Left const, Right const>::type \
+ , typename boost::proto::result_of::make_expr<TAG, DOMAIN, Left const &, Right const &>::type\
>::type const \
     operator OP(Left const &left, Right const &right) \
     { \
- return boost::proto::make_expr<TAG, DOMAIN>(left, right); \
+ return boost::proto::make_expr<TAG, DOMAIN>(boost::ref(left), boost::ref(right)); \
     } \
     /**/
 

Modified: trunk/boost/xpressive/proto/proto_fwd.hpp
==============================================================================
--- trunk/boost/xpressive/proto/proto_fwd.hpp (original)
+++ trunk/boost/xpressive/proto/proto_fwd.hpp 2008-01-30 17:10:13 EST (Wed, 30 Jan 2008)
@@ -61,6 +61,24 @@
 
 #include <boost/xpressive/proto/detail/suffix.hpp> // must be last include
 
+#ifdef BOOST_PROTO_DOXYGEN_INVOKED
+// HACKHACK so Doxygen shows inheritance from mpl::true_ and mpl::false_
+namespace boost
+{
+ /// INTERNAL ONLY
+ ///
+ namespace mpl
+ {
+ /// INTERNAL ONLY
+ ///
+ struct true_ {};
+ /// INTERNAL ONLY
+ ///
+ struct false_ {};
+ }
+}
+#endif
+
 namespace boost { namespace proto
 {
     namespace detail
@@ -498,52 +516,6 @@
         typedef make_expr<tag::if_else_> make_if_else;
         typedef make_expr<tag::function> make_function;
 
- //typedef make_expr_ref<tag::terminal> make_terminal_ref;
- //typedef make_expr_ref<tag::posit> make_posit_ref;
- //typedef make_expr_ref<tag::negate> make_negate_ref;
- //typedef make_expr_ref<tag::dereference> make_dereference_ref;
- //typedef make_expr_ref<tag::complement> make_complement_ref;
- //typedef make_expr_ref<tag::address_of> make_address_of_ref;
- //typedef make_expr_ref<tag::logical_not> make_logical_not_ref;
- //typedef make_expr_ref<tag::pre_inc> make_pre_inc_ref;
- //typedef make_expr_ref<tag::pre_dec> make_pre_dec_ref;
- //typedef make_expr_ref<tag::post_inc> make_post_inc_ref;
- //typedef make_expr_ref<tag::post_dec> make_post_dec_ref;
- //typedef make_expr_ref<tag::shift_left> make_shift_left_ref;
- //typedef make_expr_ref<tag::shift_right> make_shift_right_ref;
- //typedef make_expr_ref<tag::multiplies> make_multiplies_ref;
- //typedef make_expr_ref<tag::divides> make_divides_ref;
- //typedef make_expr_ref<tag::modulus> make_modulus_ref;
- //typedef make_expr_ref<tag::plus> make_plus_ref;
- //typedef make_expr_ref<tag::minus> make_minus_ref;
- //typedef make_expr_ref<tag::less> make_less_ref;
- //typedef make_expr_ref<tag::greater> make_greater_ref;
- //typedef make_expr_ref<tag::less_equal> make_less_equal_ref;
- //typedef make_expr_ref<tag::greater_equal> make_greater_equal_ref;
- //typedef make_expr_ref<tag::equal_to> make_equal_to_ref;
- //typedef make_expr_ref<tag::not_equal_to> make_not_equal_to_ref;
- //typedef make_expr_ref<tag::logical_or> make_logical_or_ref;
- //typedef make_expr_ref<tag::logical_and> make_logical_and_ref;
- //typedef make_expr_ref<tag::bitwise_and> make_bitwise_and_ref;
- //typedef make_expr_ref<tag::bitwise_or> make_bitwise_or_ref;
- //typedef make_expr_ref<tag::bitwise_xor> make_bitwise_xor_ref;
- //typedef make_expr_ref<tag::comma> make_comma_ref;
- //typedef make_expr_ref<tag::mem_ptr> make_mem_ptr_ref;
- //typedef make_expr_ref<tag::assign> make_assign_ref;
- //typedef make_expr_ref<tag::shift_left_assign> make_shift_left_assign_ref;
- //typedef make_expr_ref<tag::shift_right_assign> make_shift_right_assign_ref;
- //typedef make_expr_ref<tag::multiplies_assign> make_multiplies_assign_ref;
- //typedef make_expr_ref<tag::divides_assign> make_divides_assign_ref;
- //typedef make_expr_ref<tag::modulus_assign> make_modulus_assign_ref;
- //typedef make_expr_ref<tag::plus_assign> make_plus_assign_ref;
- //typedef make_expr_ref<tag::minus_assign> make_minus_assign_ref;
- //typedef make_expr_ref<tag::bitwise_and_assign> make_bitwise_and_assign_ref;
- //typedef make_expr_ref<tag::bitwise_or_assign> make_bitwise_or_assign_ref;
- //typedef make_expr_ref<tag::bitwise_xor_assign> make_bitwise_xor_assign_ref;
- //typedef make_expr_ref<tag::subscript> make_subscript_ref;
- //typedef make_expr_ref<tag::if_else_> make_if_else_ref;
- //typedef make_expr_ref<tag::function> make_function_ref;
-
         struct flatten;
         struct pop_front;
         struct reverse;
@@ -595,52 +567,6 @@
     typedef functional::make_if_else _make_if_else;
     typedef functional::make_function _make_function;
 
- //typedef functional::make_terminal_ref _make_terminal_ref;
- //typedef functional::make_posit_ref _make_posit_ref;
- //typedef functional::make_negate_ref _make_negate_ref;
- //typedef functional::make_dereference_ref _make_dereference_ref;
- //typedef functional::make_complement_ref _make_complement_ref;
- //typedef functional::make_address_of_ref _make_address_of_ref;
- //typedef functional::make_logical_not_ref _make_logical_not_ref;
- //typedef functional::make_pre_inc_ref _make_pre_inc_ref;
- //typedef functional::make_pre_dec_ref _make_pre_dec_ref;
- //typedef functional::make_post_inc_ref _make_post_inc_ref;
- //typedef functional::make_post_dec_ref _make_post_dec_ref;
- //typedef functional::make_shift_left_ref _make_shift_left_ref;
- //typedef functional::make_shift_right_ref _make_shift_right_ref;
- //typedef functional::make_multiplies_ref _make_multiplies_ref;
- //typedef functional::make_divides_ref _make_divides_ref;
- //typedef functional::make_modulus_ref _make_modulus_ref;
- //typedef functional::make_plus_ref _make_plus_ref;
- //typedef functional::make_minus_ref _make_minus_ref;
- //typedef functional::make_less_ref _make_less_ref;
- //typedef functional::make_greater_ref _make_greater_ref;
- //typedef functional::make_less_equal_ref _make_less_equal_ref;
- //typedef functional::make_greater_equal_ref _make_greater_equal_ref;
- //typedef functional::make_equal_to_ref _make_equal_to_ref;
- //typedef functional::make_not_equal_to_ref _make_not_equal_to_ref;
- //typedef functional::make_logical_or_ref _make_logical_or_ref;
- //typedef functional::make_logical_and_ref _make_logical_and_ref;
- //typedef functional::make_bitwise_and_ref _make_bitwise_and_ref;
- //typedef functional::make_bitwise_or_ref _make_bitwise_or_ref;
- //typedef functional::make_bitwise_xor_ref _make_bitwise_xor_ref;
- //typedef functional::make_comma_ref _make_comma_ref;
- //typedef functional::make_mem_ptr_ref _make_mem_ptr_ref;
- //typedef functional::make_assign_ref _make_assign_ref;
- //typedef functional::make_shift_left_assign_ref _make_shift_left_assign_ref;
- //typedef functional::make_shift_right_assign_ref _make_shift_right_assign_ref;
- //typedef functional::make_multiplies_assign_ref _make_multiplies_assign_ref;
- //typedef functional::make_divides_assign_ref _make_divides_assign_ref;
- //typedef functional::make_modulus_assign_ref _make_modulus_assign_ref;
- //typedef functional::make_plus_assign_ref _make_plus_assign_ref;
- //typedef functional::make_minus_assign_ref _make_minus_assign_ref;
- //typedef functional::make_bitwise_and_assign_ref _make_bitwise_and_assign_ref;
- //typedef functional::make_bitwise_or_assign_ref _make_bitwise_or_assign_ref;
- //typedef functional::make_bitwise_xor_assign_ref _make_bitwise_xor_assign_ref;
- //typedef functional::make_subscript_ref _make_subscript_ref;
- //typedef functional::make_if_else_ref _make_if_else_ref;
- //typedef functional::make_function_ref _make_function_ref;
-
     typedef functional::flatten _flatten;
     typedef functional::pop_front _pop_front;
     typedef functional::reverse _reverse;
@@ -715,6 +641,8 @@
         typedef arg0 arg;
         typedef arg0 left;
         typedef arg1 right;
+
+ struct _ref;
     }
 
     using transform::when;
@@ -749,6 +677,8 @@
     template<int I>
     struct _arg_c;
 
+ using transform::_ref;
+
     template<typename T>
     struct is_extension;
 

Modified: trunk/boost/xpressive/proto/transform/arg.hpp
==============================================================================
--- trunk/boost/xpressive/proto/transform/arg.hpp (original)
+++ trunk/boost/xpressive/proto/transform/arg.hpp 2008-01-30 17:10:13 EST (Wed, 30 Jan 2008)
@@ -92,6 +92,37 @@
                 return proto::arg_c<I>(expr);
             }
         };
+
+ struct _ref : proto::callable
+ {
+ template<typename Sig> struct result {};
+
+ template<typename This, typename T>
+ struct result<This(T)>
+ {
+ typedef boost::reference_wrapper<T const> type;
+ };
+
+ template<typename This, typename T>
+ struct result<This(T &)>
+ {
+ typedef boost::reference_wrapper<T> type;
+ };
+
+ template<typename T>
+ boost::reference_wrapper<T>
+ operator ()(T &t) const
+ {
+ return boost::reference_wrapper<T>(t);
+ }
+
+ template<typename T>
+ boost::reference_wrapper<T const>
+ operator ()(T const &t) const
+ {
+ return boost::reference_wrapper<T const>(t);
+ }
+ };
     }
 
     template<int I>
@@ -124,6 +155,11 @@
       : mpl::true_
     {};
 
+ template<>
+ struct is_callable<transform::_ref>
+ : mpl::true_
+ {};
+
 }}
 
 #endif

Modified: trunk/boost/xpressive/regex_primitives.hpp
==============================================================================
--- trunk/boost/xpressive/regex_primitives.hpp (original)
+++ trunk/boost/xpressive/regex_primitives.hpp 2008-01-30 17:10:13 EST (Wed, 30 Jan 2008)
@@ -608,11 +608,19 @@
 /// \brief Make a sub-expression optional. Equivalent to !as_xpr(expr).
 ///
 /// \param expr The sub-expression to make optional.
-#ifdef BOOST_XPRESSIVE_DOXYGEN_INVOKED
-template<typename Expr> detail::unspecified optional(Expr const &expr) { return 0; }
-#else
-proto::functional::make_expr<proto::tag::logical_not, proto::default_domain> const optional = {};
-#endif
+template<typename Expr>
+typename proto::result_of::make_expr<
+ proto::tag::logical_not
+ , proto::default_domain
+ , Expr const &
+>::type const
+optional(Expr const &expr)
+{
+ return proto::make_expr<
+ proto::tag::logical_not
+ , proto::default_domain
+ >(boost::ref(expr));
+}
 
 ///////////////////////////////////////////////////////////////////////////////
 /// \brief Repeat a sub-expression multiple times.
@@ -626,19 +634,33 @@
 ///
 /// \param expr The sub-expression to repeat.
 template<unsigned int Min, unsigned int Max, typename Expr>
-typename proto::result_of::make_expr<detail::generic_quant_tag<Min, Max>, proto::default_domain, Expr const>::type const
+typename proto::result_of::make_expr<
+ detail::generic_quant_tag<Min, Max>
+ , proto::default_domain
+ , Expr const &
+>::type const
 repeat(Expr const &expr)
 {
- return proto::make_expr<detail::generic_quant_tag<Min, Max>, proto::default_domain>(expr);
+ return proto::make_expr<
+ detail::generic_quant_tag<Min, Max>
+ , proto::default_domain
+ >(boost::ref(expr));
 }
 
 /// \overload
 ///
 template<unsigned int Count, typename Expr2>
-typename proto::result_of::make_expr<detail::generic_quant_tag<Count, Count>, proto::default_domain, Expr2 const>::type const
+typename proto::result_of::make_expr<
+ detail::generic_quant_tag<Count, Count>
+ , proto::default_domain
+ , Expr2 const &
+>::type const
 repeat(Expr2 const &expr2)
 {
- return proto::make_expr<detail::generic_quant_tag<Count, Count>, proto::default_domain>(expr2);
+ return proto::make_expr<
+ detail::generic_quant_tag<Count, Count>
+ , proto::default_domain
+ >(boost::ref(expr2));
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -651,11 +673,19 @@
 /// \attention keep(expr) is equivalent to the perl (?>...) extension.
 ///
 /// \param expr The sub-expression to modify.
-#ifdef BOOST_XPRESSIVE_DOXYGEN_INVOKED
-template<typename Expr> detail::unspecified keep(Expr const &expr) { return 0; }
-#else
-proto::functional::make_expr<detail::keeper_tag, proto::default_domain> const keep = {};
-#endif
+template<typename Expr>
+typename proto::result_of::make_expr<
+ detail::keeper_tag
+ , proto::default_domain
+ , Expr const &
+>::type const
+keep(Expr const &expr)
+{
+ return proto::make_expr<
+ detail::keeper_tag
+ , proto::default_domain
+ >(boost::ref(expr));
+}
 
 ///////////////////////////////////////////////////////////////////////////////
 /// \brief Look-ahead assertion.
@@ -670,11 +700,19 @@
 /// perl (?!...) extension.
 ///
 /// \param expr The sub-expression to put in the look-ahead assertion.
-#ifdef BOOST_XPRESSIVE_DOXYGEN_INVOKED
-template<typename Expr> detail::unspecified before(Expr const &expr) { return 0; }
-#else
-proto::functional::make_expr<detail::lookahead_tag, proto::default_domain> const before = {};
-#endif
+template<typename Expr>
+typename proto::result_of::make_expr<
+ detail::lookahead_tag
+ , proto::default_domain
+ , Expr const &
+>::type const
+before(Expr const &expr)
+{
+ return proto::make_expr<
+ detail::lookahead_tag
+ , proto::default_domain
+ >(boost::ref(expr));
+}
 
 ///////////////////////////////////////////////////////////////////////////////
 /// \brief Look-behind assertion.
@@ -691,11 +729,19 @@
 /// \param expr The sub-expression to put in the look-ahead assertion.
 ///
 /// \pre expr cannot match a variable number of characters.
-#ifdef BOOST_XPRESSIVE_DOXYGEN_INVOKED
-template<typename Expr> detail::unspecified after(Expr const &expr) { return 0; }
-#else
-proto::functional::make_expr<detail::lookbehind_tag, proto::default_domain> const after = {};
-#endif
+template<typename Expr>
+typename proto::result_of::make_expr<
+ detail::lookbehind_tag
+ , proto::default_domain
+ , Expr const &
+>::type const
+after(Expr const &expr)
+{
+ return proto::make_expr<
+ detail::lookbehind_tag
+ , proto::default_domain
+ >(boost::ref(expr));
+}
 
 ///////////////////////////////////////////////////////////////////////////////
 /// \brief Specify a regex traits or a std::locale.
@@ -815,10 +861,6 @@
         ignore_unused(a8);
         ignore_unused(a9);
         ignore_unused(as_xpr);
- ignore_unused(optional);
- ignore_unused(before);
- ignore_unused(after);
- ignore_unused(keep);
     }
 }
 

Modified: trunk/libs/xpressive/proto/doc/preface.qbk
==============================================================================
--- trunk/libs/xpressive/proto/doc/preface.qbk (original)
+++ trunk/libs/xpressive/proto/doc/preface.qbk 2008-01-30 17:10:13 EST (Wed, 30 Jan 2008)
@@ -7,8 +7,8 @@
 
 [section Preface]
 
-[:Something witty.]
-[:[*['-- Someone Famous]]]
+[:["There are more things in heaven and earth, Horatio, than are dreamt of in your philosophy.]]
+[:[*['-- William Shakespear]]]
 
 [heading Description]
 
@@ -64,4 +64,11 @@
 by MPL's lambda expressions, and by Aleksey Gurtovoy's
 [@http://lists.boost.org/Archives/boost/2002/11/39718.php "round" lambda] notation.
 
+[heading Further Reading]
+
+A technical paper about an earlier version of Proto was accepted into the
+[@http://lcsd.cs.tamu.edu/2007/ ACM SIGPLAN Symposium on Library-Centric Software Design LCSD'07],
+and can be found at [@http://lcsd.cs.tamu.edu/2007/final/1/1_Paper.pdf]. The
+tree transforms described in that paper differ from what exists today.
+
 [endsect]

Modified: trunk/libs/xpressive/proto/example/mixed.cpp
==============================================================================
--- trunk/libs/xpressive/proto/example/mixed.cpp (original)
+++ trunk/libs/xpressive/proto/example/mixed.cpp 2008-01-30 17:10:13 EST (Wed, 30 Jan 2008)
@@ -246,11 +246,10 @@
         proto::tag::function
       , MixedDomain
       , sin_ const
- , A const
+ , A const &
>::type sin(A const &a)
     {
- static sin_ const s = {};
- return proto::make_expr<proto::tag::function, MixedDomain>(s, a);
+ return proto::make_expr<proto::tag::function, MixedDomain>(sin_(), boost::ref(a));
     }
 
     template<typename FwdIter, typename Expr, typename Op>

Modified: trunk/libs/xpressive/proto/test/make_expr.cpp
==============================================================================
--- trunk/libs/xpressive/proto/test/make_expr.cpp (original)
+++ trunk/libs/xpressive/proto/test/make_expr.cpp 2008-01-30 17:10:13 EST (Wed, 30 Jan 2008)
@@ -7,7 +7,8 @@
 
 #include <sstream>
 #include <boost/xpressive/proto/proto.hpp>
-#include <boost/fusion/include/vector.hpp>
+#include <boost/xpressive/proto/transform.hpp>
+#include <boost/fusion/tuple.hpp>
 #include <boost/test/unit_test.hpp>
 
 using namespace boost;
@@ -30,85 +31,186 @@
 void test_make_expr()
 {
     int i = 42;
- terminal<int const &>::type t1 = make_expr<tag::terminal>(1);
- terminal<int &>::type t2 = make_expr<tag::terminal>(i);
- posit<terminal<int const &>::type>::type p1 = make_expr<tag::posit>(1);
- posit<terminal<int &>::type>::type p2 = make_expr<tag::posit>(i);
+ terminal<int>::type t1 = make_expr<tag::terminal>(1);
+ terminal<int>::type t2 = make_expr<tag::terminal>(i);
+ posit<terminal<int>::type>::type p1 = make_expr<tag::posit>(1);
+ posit<terminal<int>::type>::type p2 = make_expr<tag::posit>(i);
     BOOST_CHECK_EQUAL(proto::arg(proto::arg(p2)), 42);
 
- ewrap<posit<ewrap<terminal<int &>::type> >::type> p3 = make_expr<tag::posit, mydomain>(i);
+ ewrap<posit<ewrap<terminal<int>::type> >::type> p3 = make_expr<tag::posit, mydomain>(i);
     BOOST_CHECK_EQUAL(proto::arg(proto::arg(p3)), 42);
 
     ewrap<plus<
- proto::ref_<ewrap<posit<ewrap<terminal<int &>::type> >::type> >
- , ewrap<terminal<int const &>::type>
+ ewrap<posit<ewrap<terminal<int>::type> >::type>
+ , ewrap<terminal<int>::type>
>::type> p4 = make_expr<tag::plus>(p3, 0);
     BOOST_CHECK_EQUAL(proto::arg(proto::arg(proto::left(p4))), 42);
 }
 
-void test_make_expr2()
+void test_make_expr_ref()
 {
     int i = 42;
- terminal<int const &>::type t1 = functional::make_expr<tag::terminal>()(1);
- terminal<int &>::type t2 = functional::make_expr<tag::terminal>()(i);
- posit<terminal<int const &>::type>::type p1 = functional::make_expr<tag::posit>()(1);
- posit<terminal<int &>::type>::type p2 = functional::make_expr<tag::posit>()(i);
+ terminal<int const &>::type t1 = make_expr<tag::terminal>(boost::cref(1)); // DANGEROUS
+ terminal<int &>::type t2 = make_expr<tag::terminal>(boost::ref(i));
+ BOOST_CHECK_EQUAL(&i, &proto::arg(t2));
+ posit<terminal<int const &>::type>::type p1 = make_expr<tag::posit>(boost::cref(1)); // DANGEROUS
+ posit<terminal<int &>::type>::type p2 = make_expr<tag::posit>(boost::ref(i));
     BOOST_CHECK_EQUAL(proto::arg(proto::arg(p2)), 42);
 
- ewrap<posit<ewrap<terminal<int &>::type> >::type> p3 = functional::make_expr<tag::posit, mydomain>()(i);
+ ewrap<posit<ewrap<terminal<int &>::type> >::type> p3 = make_expr<tag::posit, mydomain>(boost::ref(i));
     BOOST_CHECK_EQUAL(proto::arg(proto::arg(p3)), 42);
 
     ewrap<plus<
         proto::ref_<ewrap<posit<ewrap<terminal<int &>::type> >::type> >
- , ewrap<terminal<int const &>::type>
+ , ewrap<terminal<int>::type>
+ >::type> p4 = make_expr<tag::plus>(boost::ref(p3), 0);
+ BOOST_CHECK_EQUAL(proto::arg(proto::arg(proto::left(p4))), 42);
+}
+
+void test_make_expr_functional()
+{
+ int i = 42;
+ terminal<int>::type t1 = functional::make_expr<tag::terminal>()(1);
+ terminal<int>::type t2 = functional::make_expr<tag::terminal>()(i);
+ posit<terminal<int>::type>::type p1 = functional::make_expr<tag::posit>()(1);
+ posit<terminal<int>::type>::type p2 = functional::make_expr<tag::posit>()(i);
+ BOOST_CHECK_EQUAL(proto::arg(proto::arg(p2)), 42);
+
+ ewrap<posit<ewrap<terminal<int>::type> >::type> p3 = functional::make_expr<tag::posit, mydomain>()(i);
+ BOOST_CHECK_EQUAL(proto::arg(proto::arg(p3)), 42);
+
+ ewrap<plus<
+ ewrap<posit<ewrap<terminal<int>::type> >::type>
+ , ewrap<terminal<int>::type>
>::type> p4 = functional::make_expr<tag::plus, mydomain>()(p3, 0);
     BOOST_CHECK_EQUAL(proto::arg(proto::arg(proto::left(p4))), 42);
 }
 
-void test_unpack_expr()
+void test_make_expr_functional_ref()
 {
     int i = 42;
- fusion::vector<int> v1(1);
- fusion::vector<int&> v2(i);
- terminal<int const &>::type t1 = unpack_expr<tag::terminal>(v1);
- terminal<int &>::type t2 = unpack_expr<tag::terminal>(v2);
- posit<terminal<int const &>::type>::type p1 = unpack_expr<tag::posit>(v1);
- posit<terminal<int &>::type>::type p2 = unpack_expr<tag::posit>(v2);
+ terminal<int const &>::type t1 = functional::make_expr<tag::terminal>()(boost::cref(1)); // DANGEROUS
+ terminal<int &>::type t2 = functional::make_expr<tag::terminal>()(boost::ref(i));
+ BOOST_CHECK_EQUAL(&i, &proto::arg(t2));
+ posit<terminal<int const &>::type>::type p1 = functional::make_expr<tag::posit>()(boost::cref(1)); // DANGEROUS
+ posit<terminal<int &>::type>::type p2 = functional::make_expr<tag::posit>()(boost::ref(i));
     BOOST_CHECK_EQUAL(proto::arg(proto::arg(p2)), 42);
 
- ewrap<posit<ewrap<terminal<int &>::type> >::type> p3 = unpack_expr<tag::posit, mydomain>(v2);
+ ewrap<posit<ewrap<terminal<int &>::type> >::type> p3 = functional::make_expr<tag::posit, mydomain>()(boost::ref(i));
     BOOST_CHECK_EQUAL(proto::arg(proto::arg(p3)), 42);
 
- fusion::vector<ewrap<posit<ewrap<terminal<int &>::type> >::type> &, int> v3(p3, 0);
     ewrap<plus<
         proto::ref_<ewrap<posit<ewrap<terminal<int &>::type> >::type> >
- , ewrap<terminal<int const &>::type>
- >::type> p4 = unpack_expr<tag::plus>(v3);
+ , ewrap<terminal<int>::type>
+ >::type> p4 = functional::make_expr<tag::plus, mydomain>()(boost::ref(p3), 0);
     BOOST_CHECK_EQUAL(proto::arg(proto::arg(proto::left(p4))), 42);
 }
 
-void test_unpack_expr2()
+void test_unpack_expr()
 {
     int i = 42;
- fusion::vector<int> v1(1);
- fusion::vector<int&> v2(i);
- terminal<int const &>::type t1 = functional::unpack_expr<tag::terminal>()(v1);
- terminal<int &>::type t2 = functional::unpack_expr<tag::terminal>()(v2);
- posit<terminal<int const &>::type>::type p1 = functional::unpack_expr<tag::posit>()(v1);
- posit<terminal<int &>::type>::type p2 = functional::unpack_expr<tag::posit>()(v2);
+ terminal<int>::type t1 = unpack_expr<tag::terminal>(fusion::make_tuple(1));
+ terminal<int &>::type t2 = unpack_expr<tag::terminal>(fusion::make_tuple(boost::ref(i)));
+ posit<terminal<int>::type>::type p1 = unpack_expr<tag::posit>(fusion::make_tuple(1));
+ posit<terminal<int &>::type>::type p2 = unpack_expr<tag::posit>(fusion::make_tuple(boost::ref(i)));
     BOOST_CHECK_EQUAL(proto::arg(proto::arg(p2)), 42);
 
- ewrap<posit<ewrap<terminal<int &>::type> >::type> p3 = functional::unpack_expr<tag::posit, mydomain>()(v2);
+ ewrap<posit<ewrap<terminal<int &>::type> >::type> p3 = unpack_expr<tag::posit, mydomain>(fusion::make_tuple(boost::ref(i)));
     BOOST_CHECK_EQUAL(proto::arg(proto::arg(p3)), 42);
 
- fusion::vector<ewrap<posit<ewrap<terminal<int &>::type> >::type> &, int> v3(p3, 0);
     ewrap<plus<
- proto::ref_<ewrap<posit<ewrap<terminal<int &>::type> >::type> >
- , ewrap<terminal<int const &>::type>
- >::type> p4 = functional::unpack_expr<tag::plus>()(v3);
+ ref_<ewrap<posit<ewrap<terminal<int &>::type> >::type> >
+ , ewrap<terminal<int>::type>
+ >::type> p4 = unpack_expr<tag::plus>(fusion::make_tuple(boost::ref(p3), 0));
+ BOOST_CHECK_EQUAL(proto::arg(proto::arg(proto::left(p4))), 42);
+}
+
+void test_unpack_expr_functional()
+{
+ int i = 42;
+ terminal<int>::type t1 = functional::unpack_expr<tag::terminal>()(fusion::make_tuple(1));
+ terminal<int &>::type t2 = functional::unpack_expr<tag::terminal>()(fusion::make_tuple(boost::ref(i)));
+ posit<terminal<int>::type>::type p1 = functional::unpack_expr<tag::posit>()(fusion::make_tuple(1));
+ posit<terminal<int &>::type>::type p2 = functional::unpack_expr<tag::posit>()(fusion::make_tuple(boost::ref(i)));
+ BOOST_CHECK_EQUAL(proto::arg(proto::arg(p2)), 42);
+
+ ewrap<posit<ewrap<terminal<int &>::type> >::type> p3 = functional::unpack_expr<tag::posit, mydomain>()(fusion::make_tuple(boost::ref(i)));
+ BOOST_CHECK_EQUAL(proto::arg(proto::arg(p3)), 42);
+
+ ewrap<plus<
+ ref_<ewrap<posit<ewrap<terminal<int &>::type> >::type> >
+ , ewrap<terminal<int>::type>
+ >::type> p4 = functional::unpack_expr<tag::plus>()(fusion::make_tuple(boost::ref(p3), 0));
     BOOST_CHECK_EQUAL(proto::arg(proto::arg(proto::left(p4))), 42);
 }
 
+#if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
+#define _ref(x) call<_ref(x)>
+#define Minus(x) call<Minus(x)>
+#endif
+
+// Turn all terminals held by reference into ones held by value
+struct ByVal
+ : or_<
+ when<terminal<_>, _make_terminal(_arg)>
+ , when<nary_expr<_, vararg<ByVal> > >
+ >
+{};
+
+// Turn all terminals held by value into ones held by reference (not safe in general)
+struct ByRef
+ : or_<
+ when<terminal<_>, _make_terminal(_ref(_arg))>
+ , when<nary_expr<_, vararg<ByRef> > >
+ >
+{};
+
+// turn all plus noded to minus nodes:
+struct Minus
+ : or_<
+ when<terminal<_> >
+ , when<plus<Minus, Minus>, _make_minus(Minus(_left), Minus(_right)) >
+ >
+{};
+
+struct Square
+ : or_<
+ // Not creating new terminal nodes here,
+ // so hold the existing terminals by reference:
+ when<terminal<_>, _make_multiplies(_ref(_), _ref(_))>
+ , when<plus<Square, Square> >
+ >
+{};
+
+#if BOOST_WORKAROUND(BOOST_MSVC, == 1310)
+#undef _ref
+#undef Minus
+#endif
+
+void test_make_expr_transform()
+{
+ int x = 0;
+ plus<
+ terminal<int>::type
+ , terminal<int>::type
+ >::type t1 = ByVal()(as_expr(1) + 1, x, x);
+
+ plus<
+ terminal<int const &>::type
+ , terminal<int const &>::type
+ >::type t2 = ByRef()(as_expr(1) + 1, x, x);
+
+ minus<
+ terminal<int>::type
+ , terminal<int const &>::type
+ >::type t3 = Minus()(as_expr(1) + 1, x, x);
+
+ plus<
+ multiplies<ref_<terminal<int>::type const>, ref_<terminal<int>::type const> >::type
+ , multiplies<ref_<terminal<int const &>::type const>, ref_<terminal<int const &>::type const> >::type
+ >::type t4 = Square()(as_expr(1) + 1, x, x);
+}
+
 using namespace unit_test;
 ///////////////////////////////////////////////////////////////////////////////
 // init_unit_test_suite
@@ -118,9 +220,12 @@
     test_suite *test = BOOST_TEST_SUITE("test make_expr, unpack_expr and friends");
 
     test->add(BOOST_TEST_CASE(&test_make_expr));
- test->add(BOOST_TEST_CASE(&test_make_expr2));
+ test->add(BOOST_TEST_CASE(&test_make_expr_ref));
+ test->add(BOOST_TEST_CASE(&test_make_expr_functional));
+ test->add(BOOST_TEST_CASE(&test_make_expr_functional_ref));
     test->add(BOOST_TEST_CASE(&test_unpack_expr));
- test->add(BOOST_TEST_CASE(&test_unpack_expr2));
+ test->add(BOOST_TEST_CASE(&test_unpack_expr_functional));
+ test->add(BOOST_TEST_CASE(&test_make_expr_transform));
 
     return test;
 }


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk