1 ///////////////////////////////////////////////////////////////////////////////
2 /// \file deep_copy.hpp
3 /// Replace all nodes stored by reference by nodes stored by value.
4 //
5 //  Copyright 2008 Eric Niebler. Distributed under the Boost
6 //  Software License, Version 1.0. (See accompanying file
7 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
8 
9 #ifndef BOOST_PROTO_DEEP_COPY_HPP_EAN_11_21_2006
10 #define BOOST_PROTO_DEEP_COPY_HPP_EAN_11_21_2006
11 
12 #include <boost/preprocessor/cat.hpp>
13 #include <boost/preprocessor/repetition/enum.hpp>
14 #include <boost/preprocessor/iteration/iterate.hpp>
15 #include <boost/mpl/if.hpp>
16 #include <boost/type_traits/remove_reference.hpp>
17 #include <boost/proto/proto_fwd.hpp>
18 #include <boost/proto/args.hpp>
19 #include <boost/proto/expr.hpp>
20 
21 namespace boost { namespace proto
22 {
23     namespace detail
24     {
25         template<typename Expr, long Arity = Expr::proto_arity_c>
26         struct deep_copy_impl;
27 
28         template<typename Expr>
29         struct deep_copy_impl<Expr, 0>
30         {
31             typedef
32                 typename base_expr<
33                     typename Expr::proto_domain
34                   , tag::terminal
35                   , term<typename term_traits<typename Expr::proto_child0>::value_type>
36                 >::type
37             expr_type;
38 
39             typedef typename Expr::proto_generator proto_generator;
40             typedef typename proto_generator::template result<proto_generator(expr_type)>::type result_type;
41 
42             template<typename Expr2, typename S, typename D>
operator ()boost::proto::detail::deep_copy_impl43             result_type operator()(Expr2 const &e, S const &, D const &) const
44             {
45                 return proto_generator()(expr_type::make(e.proto_base().child0));
46             }
47         };
48     }
49 
50     namespace result_of
51     {
52         /// \brief A metafunction for calculating the return type
53         /// of \c proto::deep_copy().
54         ///
55         /// A metafunction for calculating the return type
56         /// of \c proto::deep_copy(). The type parameter \c Expr
57         /// should be the type of a Proto expression tree.
58         /// It should not be a reference type, nor should it
59         /// be cv-qualified.
60         template<typename Expr>
61         struct deep_copy
62         {
63             typedef
64                 typename detail::deep_copy_impl<
65                     BOOST_PROTO_UNCVREF(Expr)
66                 >::result_type
67             type;
68         };
69     }
70 
71     namespace functional
72     {
73         /// \brief A PolymorphicFunctionObject type for deep-copying
74         /// Proto expression trees.
75         ///
76         /// A PolymorphicFunctionObject type for deep-copying
77         /// Proto expression trees. When a tree is deep-copied,
78         /// all internal nodes and most terminals held by reference
79         /// are instead held by value.
80         ///
81         /// \attention Terminals of reference-to-function type are
82         /// left unchanged. Terminals of reference-to-array type are
83         /// stored by value, which can cause a large amount of data
84         /// to be passed by value and stored on the stack.
85         struct deep_copy
86         {
87             BOOST_PROTO_CALLABLE()
88 
89             template<typename Sig>
90             struct result;
91 
92             template<typename This, typename Expr>
93             struct result<This(Expr)>
94             {
95                 typedef
96                     typename detail::deep_copy_impl<
97                         BOOST_PROTO_UNCVREF(Expr)
98                     >::result_type
99                 type;
100             };
101 
102             /// \brief Deep-copies a Proto expression tree, turning all
103             /// nodes and terminals held by reference into ones held by
104             /// value.
105             template<typename Expr>
106             typename result_of::deep_copy<Expr>::type
operator ()boost::proto::functional::deep_copy107             operator()(Expr const &e) const
108             {
109                 return proto::detail::deep_copy_impl<Expr>()(e, 0, 0);
110             }
111         };
112     }
113 
114     /// \brief A function for deep-copying
115     /// Proto expression trees.
116     ///
117     /// A function for deep-copying
118     /// Proto expression trees. When a tree is deep-copied,
119     /// all internal nodes and most terminals held by reference
120     /// are instead held by value.
121     ///
122     /// \attention Terminals of reference-to-function type are
123     /// left unchanged.
124     ///
125     /// \sa proto::functional::deep_copy.
126     template<typename Expr>
127     typename proto::result_of::deep_copy<Expr>::type
deep_copy(Expr const & e)128     deep_copy(Expr const &e)
129     {
130         return proto::detail::deep_copy_impl<Expr>()(e, 0, 0);
131     }
132 
133     /// \brief A PrimitiveTransform for deep-copying
134     /// Proto expression trees.
135     ///
136     /// A PrimitiveTransform for deep-copying
137     /// Proto expression trees. When a tree is deep-copied,
138     /// all internal nodes and most terminals held by reference
139     /// are instead held by value.
140     ///
141     /// \attention Terminals of reference-to-function type are
142     /// left unchanged.
143     ///
144     /// \sa proto::functional::deep_copy.
145     struct _deep_copy
146       : proto::transform<_deep_copy>
147     {
148         template<typename E, typename S, typename D>
149         struct impl
150           : detail::deep_copy_impl<BOOST_PROTO_UNCVREF(E)>
151         {};
152     };
153 
154     namespace detail
155     {
156         // include the definition of deep_copy_impl
157         #include <boost/proto/detail/deep_copy.hpp>
158     }
159 
160 }}
161 
162 #endif // BOOST_PROTO_COMPILER_DEEP_COPY_HPP_EAN_11_21_2006
163 
164