#ifndef BOOST_PP_IS_ITERATING | |
/////////////////////////////////////////////////////////////////////////////// | |
/// \file deep_copy.hpp | |
/// Replace all nodes stored by reference by nodes stored by value. | |
// | |
// 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_DEEP_COPY_HPP_EAN_11_21_2006 | |
#define BOOST_PROTO_DEEP_COPY_HPP_EAN_11_21_2006 | |
#include <boost/preprocessor/cat.hpp> | |
#include <boost/preprocessor/repetition/enum.hpp> | |
#include <boost/preprocessor/iteration/iterate.hpp> | |
#include <boost/mpl/if.hpp> | |
#include <boost/type_traits/remove_reference.hpp> | |
#include <boost/proto/proto_fwd.hpp> | |
#include <boost/proto/args.hpp> | |
#include <boost/proto/expr.hpp> | |
namespace boost { namespace proto | |
{ | |
namespace detail | |
{ | |
template<typename Expr, long Arity = Expr::proto_arity_c> | |
struct deep_copy_impl; | |
template<typename Expr> | |
struct deep_copy_impl<Expr, 0> | |
{ | |
typedef | |
typename base_expr< | |
typename Expr::proto_domain | |
, tag::terminal | |
, term<typename term_traits<typename Expr::proto_child0>::value_type> | |
>::type | |
expr_type; | |
typedef typename Expr::proto_generator proto_generator; | |
typedef typename proto_generator::template result<proto_generator(expr_type)>::type result_type; | |
template<typename Expr2, typename S, typename D> | |
result_type operator()(Expr2 const &e, S const &, D const &) const | |
{ | |
return proto_generator()(expr_type::make(e.proto_base().child0)); | |
} | |
}; | |
} | |
namespace result_of | |
{ | |
/// \brief A metafunction for calculating the return type | |
/// of \c proto::deep_copy(). | |
/// | |
/// A metafunction for calculating the return type | |
/// of \c proto::deep_copy(). The type parameter \c Expr | |
/// should be the type of a Proto expression tree. | |
/// It should not be a reference type, nor should it | |
/// be cv-qualified. | |
template<typename Expr> | |
struct deep_copy | |
{ | |
typedef | |
typename detail::deep_copy_impl< | |
BOOST_PROTO_UNCVREF(Expr) | |
>::result_type | |
type; | |
}; | |
} | |
namespace functional | |
{ | |
/// \brief A PolymorphicFunctionObject type for deep-copying | |
/// Proto expression trees. | |
/// | |
/// A PolymorphicFunctionObject type for deep-copying | |
/// Proto expression trees. When a tree is deep-copied, | |
/// all internal nodes and most terminals held by reference | |
/// are instead held by value. | |
/// | |
/// \attention Terminals of reference-to-function type are | |
/// left unchanged. Terminals of reference-to-array type are | |
/// stored by value, which can cause a large amount of data | |
/// to be passed by value and stored on the stack. | |
struct deep_copy | |
{ | |
BOOST_PROTO_CALLABLE() | |
template<typename Sig> | |
struct result; | |
template<typename This, typename Expr> | |
struct result<This(Expr)> | |
{ | |
typedef | |
typename detail::deep_copy_impl< | |
BOOST_PROTO_UNCVREF(Expr) | |
>::result_type | |
type; | |
}; | |
/// \brief Deep-copies a Proto expression tree, turning all | |
/// nodes and terminals held by reference into ones held by | |
/// value. | |
template<typename Expr> | |
typename result_of::deep_copy<Expr>::type | |
operator()(Expr const &e) const | |
{ | |
return proto::detail::deep_copy_impl<Expr>()(e, 0, 0); | |
} | |
}; | |
} | |
/// \brief A function for deep-copying | |
/// Proto expression trees. | |
/// | |
/// A function for deep-copying | |
/// Proto expression trees. When a tree is deep-copied, | |
/// all internal nodes and most terminals held by reference | |
/// are instead held by value. | |
/// | |
/// \attention Terminals of reference-to-function type are | |
/// left unchanged. | |
/// | |
/// \sa proto::functional::deep_copy. | |
template<typename Expr> | |
typename proto::result_of::deep_copy<Expr>::type | |
deep_copy(Expr const &e) | |
{ | |
return proto::detail::deep_copy_impl<Expr>()(e, 0, 0); | |
} | |
/// \brief A PrimitiveTransform for deep-copying | |
/// Proto expression trees. | |
/// | |
/// A PrimitiveTransform for deep-copying | |
/// Proto expression trees. When a tree is deep-copied, | |
/// all internal nodes and most terminals held by reference | |
/// are instead held by value. | |
/// | |
/// \attention Terminals of reference-to-function type are | |
/// left unchanged. | |
/// | |
/// \sa proto::functional::deep_copy. | |
struct _deep_copy | |
: proto::transform<_deep_copy> | |
{ | |
template<typename E, typename S, typename D> | |
struct impl | |
: detail::deep_copy_impl<BOOST_PROTO_UNCVREF(E)> | |
{}; | |
}; | |
namespace detail | |
{ | |
#define BOOST_PROTO_DEFINE_DEEP_COPY_TYPE(Z, N, DATA) \ | |
typename deep_copy_impl< \ | |
typename remove_reference< \ | |
typename Expr::BOOST_PP_CAT(proto_child, N) \ | |
>::type::proto_derived_expr \ | |
>::result_type \ | |
/**/ | |
#define BOOST_PROTO_DEFINE_DEEP_COPY_FUN(Z, N, DATA) \ | |
proto::deep_copy(e.proto_base().BOOST_PP_CAT(child, N)) \ | |
/**/ | |
#define BOOST_PP_ITERATION_PARAMS_1 (3, (1, BOOST_PROTO_MAX_ARITY, <boost/proto/deep_copy.hpp>)) | |
#include BOOST_PP_ITERATE() | |
#undef BOOST_PROTO_DEFINE_DEEP_COPY_FUN | |
#undef BOOST_PROTO_DEFINE_DEEP_COPY_TYPE | |
} | |
}} | |
#endif // BOOST_PROTO_COMPILER_DEEP_COPY_HPP_EAN_11_21_2006 | |
#else | |
#define N BOOST_PP_ITERATION() | |
template<typename Expr> | |
struct deep_copy_impl<Expr, N> | |
{ | |
typedef | |
typename base_expr< | |
typename Expr::proto_domain | |
, typename Expr::proto_tag | |
, BOOST_PP_CAT(list, N)< | |
BOOST_PP_ENUM(N, BOOST_PROTO_DEFINE_DEEP_COPY_TYPE, ~) | |
> | |
>::type | |
expr_type; | |
typedef typename Expr::proto_generator proto_generator; | |
typedef typename proto_generator::template result<proto_generator(expr_type)>::type result_type; | |
template<typename Expr2, typename S, typename D> | |
result_type operator()(Expr2 const &e, S const &, D const &) const | |
{ | |
expr_type const that = { | |
BOOST_PP_ENUM(N, BOOST_PROTO_DEFINE_DEEP_COPY_FUN, ~) | |
}; | |
return proto_generator()(that); | |
} | |
}; | |
#undef N | |
#endif |