deep_copy.hpp 5.3 KB

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