1 #ifndef BOOST_PP_IS_ITERATING
2 ///////////////////////////////////////////////////////////////////////////////
4 /// Contains definition of expr\<\> class template.
6 // Copyright 2008 Eric Niebler. Distributed under the Boost
7 // Software License, Version 1.0. (See accompanying file
8 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
10 #ifndef BOOST_PROTO_EXPR_HPP_EAN_04_01_2005
11 #define BOOST_PROTO_EXPR_HPP_EAN_04_01_2005
13 #include <boost/proto/detail/prefix.hpp>
14 #include <boost/preprocessor/cat.hpp>
15 #include <boost/preprocessor/arithmetic/dec.hpp>
16 #include <boost/preprocessor/selection/max.hpp>
17 #include <boost/preprocessor/iteration/iterate.hpp>
18 #include <boost/preprocessor/repetition/repeat.hpp>
19 #include <boost/preprocessor/repetition/repeat_from_to.hpp>
20 #include <boost/preprocessor/repetition/enum_trailing.hpp>
21 #include <boost/preprocessor/repetition/enum_params.hpp>
22 #include <boost/preprocessor/repetition/enum_binary_params.hpp>
23 #include <boost/preprocessor/repetition/enum_trailing_params.hpp>
24 #include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp>
25 #include <boost/utility/addressof.hpp>
26 #include <boost/proto/proto_fwd.hpp>
27 #include <boost/proto/args.hpp>
28 #include <boost/proto/traits.hpp>
29 #include <boost/proto/detail/suffix.hpp>
31 #if defined(_MSC_VER) && (_MSC_VER >= 1020)
32 # pragma warning(push)
33 # pragma warning(disable : 4510) // default constructor could not be generated
34 # pragma warning(disable : 4512) // assignment operator could not be generated
35 # pragma warning(disable : 4610) // user defined constructor required
38 namespace boost
{ namespace proto
45 #define BOOST_PROTO_CHILD(Z, N, DATA) \
46 typedef typename Args::BOOST_PP_CAT(child, N) BOOST_PP_CAT(proto_child, N); \
47 BOOST_PP_CAT(proto_child, N) BOOST_PP_CAT(child, N); \
52 #define BOOST_PROTO_VOID(Z, N, DATA) \
53 typedef void BOOST_PP_CAT(proto_child, N); \
56 struct not_a_valid_type
63 template<typename Tag
, typename Arg
>
64 struct address_of_hack
66 typedef not_a_valid_type type
;
69 template<typename Expr
>
70 struct address_of_hack
<proto::tag::address_of
, Expr
&>
75 template<typename X
, std::size_t N
, typename Y
>
76 void checked_copy(X (&x
)[N
], Y (&y
)[N
])
78 for(std::size_t i
= 0; i
< N
; ++i
)
84 template<typename T
, std::size_t N
>
88 template<typename T
, std::size_t N
>
89 struct if_is_array
<T
[N
], N
>
98 /// \brief A helper metafunction for computing the
99 /// return type of \c proto::expr\<\>::operator().
100 template<typename Sig
, typename This
, typename Domain
>
103 #define BOOST_PP_ITERATION_PARAMS_1 (3, (0, BOOST_PP_DEC(BOOST_PROTO_MAX_FUNCTION_CALL_ARITY), <boost/proto/detail/funop.hpp>))
104 #include BOOST_PP_ITERATE()
107 // TODO consider adding a basic_expr<> that doesn't have operator=,
108 // operator[] or operator() for use by BOOST_PROTO_BASIC_EXTENDS().
109 // Those member functions are unused in that case, and only slow
110 // down instantiations. basic_expr::proto_base_expr can still be
111 // expr<> because uses of proto_base_expr in proto::matches<> shouldn't
112 // case the expr<> type to be instantiated. (<-- Check that assumtion!)
113 // OR, should expr<>::proto_base_expr be a typedef for basic_expr<>?
115 BOOST_PROTO_BEGIN_ADL_NAMESPACE(exprns_
)
116 #define BOOST_PP_ITERATION_PARAMS_1 (3, (0, BOOST_PROTO_MAX_ARITY, <boost/proto/expr.hpp>))
117 #include BOOST_PP_ITERATE()
118 BOOST_PROTO_END_ADL_NAMESPACE(exprns_
)
120 #undef BOOST_PROTO_CHILD
121 #undef BOOST_PROTO_VOID
123 /// \brief Lets you inherit the interface of an expression
124 /// while hiding from Proto the fact that the type is a Proto
126 template<typename Expr
>
132 explicit unexpr(Expr
const &expr
)
136 using Expr::operator =;
141 #if defined(_MSC_VER) && (_MSC_VER >= 1020)
142 # pragma warning(pop)
145 #endif // BOOST_PROTO_EXPR_HPP_EAN_04_01_2005
147 // For gcc 4.4 compatability, we must include the
148 // BOOST_PP_ITERATION_DEPTH test inside an #else clause.
149 #else // BOOST_PP_IS_ITERATING
150 #if BOOST_PP_ITERATION_DEPTH() == 1
152 #define ARG_COUNT BOOST_PP_MAX(1, BOOST_PP_ITERATION())
153 #define IS_TERMINAL 0 == BOOST_PP_ITERATION()
155 /// \brief Representation of a node in an expression tree.
157 /// \c proto::expr\<\> is a node in an expression template tree. It
158 /// is a container for its child sub-trees. It also serves as
159 /// the terminal nodes of the tree.
161 /// \c Tag is type that represents the operation encoded by
162 /// this expression. It is typically one of the structs
163 /// in the \c boost::proto::tag namespace, but it doesn't
166 /// \c Args is a type list representing the type of the children
167 /// of this expression. It is an instantiation of one
168 /// of \c proto::list1\<\>, \c proto::list2\<\>, etc. The
169 /// child types must all themselves be either \c expr\<\>
170 /// or <tt>proto::expr\<\>&</tt>. If \c Args is an
171 /// instantiation of \c proto::term\<\> then this
172 /// \c expr\<\> type represents a terminal expression;
173 /// the parameter to the \c proto::term\<\> template
174 /// represents the terminal's value type.
176 /// \c Arity is an integral constant representing the number of child
177 /// nodes this node contains. If \c Arity is 0, then this
178 /// node is a terminal.
180 /// \c proto::expr\<\> is a valid Fusion random-access sequence, where
181 /// the elements of the sequence are the child expressions.
182 template<typename Tag
, typename Args
>
183 struct expr
<Tag
, Args
, BOOST_PP_ITERATION() >
185 typedef Tag proto_tag
;
186 BOOST_STATIC_CONSTANT(long, proto_arity_c
= BOOST_PP_ITERATION());
187 typedef mpl::long_
<BOOST_PP_ITERATION() > proto_arity
;
188 typedef expr proto_base_expr
;
189 typedef Args proto_args
;
190 typedef default_domain proto_domain
;
191 BOOST_PROTO_FUSION_DEFINE_TAG(proto::tag::proto_expr
)
192 typedef expr proto_derived_expr
;
193 typedef void proto_is_expr_
; /**< INTERNAL ONLY */
195 BOOST_PP_REPEAT(ARG_COUNT
, BOOST_PROTO_CHILD
, ~)
196 BOOST_PP_REPEAT_FROM_TO(ARG_COUNT
, BOOST_PROTO_MAX_ARITY
, BOOST_PROTO_VOID
, ~)
200 expr
const &proto_base() const
212 /// \return A new \c expr\<\> object initialized with the specified
215 template<BOOST_PP_ENUM_PARAMS(ARG_COUNT
, typename A
)>
216 static expr
const make(BOOST_PP_ENUM_BINARY_PARAMS(ARG_COUNT
, A
, const &a
))
218 expr that
= {BOOST_PP_ENUM_PARAMS(ARG_COUNT
, a
)};
225 template<typename A0
>
226 static expr
const make(A0
&a0
)
234 template<typename A0
, std::size_t N
>
235 static expr
const make(A0 (&a0
)[N
], typename
detail::if_is_array
<proto_child0
, N
>::type
= 0)
238 detail::checked_copy(a0
, that
.child0
);
244 template<typename A0
, std::size_t N
>
245 static expr
const make(A0
const (&a0
)[N
], typename
detail::if_is_array
<proto_child0
, N
>::type
= 0)
248 detail::checked_copy(a0
, that
.child0
);
253 #if 1 == BOOST_PP_ITERATION()
254 /// If \c Tag is \c boost::proto::tag::address_of and \c proto_child0 is
255 /// <tt>T&</tt>, then \c address_of_hack_type_ is <tt>T*</tt>.
256 /// Otherwise, it is some undefined type.
257 typedef typename
detail::address_of_hack
<Tag
, proto_child0
>::type address_of_hack_type_
;
259 /// \return The address of <tt>this->child0</tt> if \c Tag is
260 /// \c boost::proto::tag::address_of. Otherwise, this function will
263 /// \attention Proto overloads <tt>operator&</tt>, which means that
264 /// proto-ified objects cannot have their addresses taken, unless we use
265 /// the following hack to make \c &x implicitly convertible to \c X*.
266 operator address_of_hack_type_() const
268 return boost::addressof(this->child0
);
273 typedef detail::not_a_valid_type address_of_hack_type_
;
278 /// \param a The rhs.
279 /// \return A new \c expr\<\> node representing an assignment of \c a to \c *this.
283 , list2
<expr
const &, typename
result_of::as_child
<A
>::type
>
285 operator =(A
&a
) const
289 , list2
<expr
const &, typename
result_of::as_child
<A
>::type
>
290 > that
= {*this, proto::as_child(a
)};
299 , list2
<expr
const &, typename
result_of::as_child
<A
const>::type
>
301 operator =(A
const &a
) const
305 , list2
<expr
const &, typename
result_of::as_child
<A
const>::type
>
306 > that
= {*this, proto::as_child(a
)};
316 , list2
<expr
&, typename
result_of::as_child
<A
>::type
>
322 , list2
<expr
&, typename
result_of::as_child
<A
>::type
>
323 > that
= {*this, proto::as_child(a
)};
332 , list2
<expr
&, typename
result_of::as_child
<A
const>::type
>
334 operator =(A
const &a
)
338 , list2
<expr
&, typename
result_of::as_child
<A
const>::type
>
339 > that
= {*this, proto::as_child(a
)};
346 /// \param a The rhs.
347 /// \return A new \c expr\<\> node representing \c *this subscripted with \c a.
350 proto::tag::subscript
351 , list2
<expr
const &, typename
result_of::as_child
<A
>::type
>
353 operator [](A
&a
) const
356 proto::tag::subscript
357 , list2
<expr
const &, typename
result_of::as_child
<A
>::type
>
358 > that
= {*this, proto::as_child(a
)};
366 proto::tag::subscript
367 , list2
<expr
const &, typename
result_of::as_child
<A
const>::type
> > const
368 operator [](A
const &a
) const
371 proto::tag::subscript
372 , list2
<expr
const &, typename
result_of::as_child
<A
const>::type
>
373 > that
= {*this, proto::as_child(a
)};
382 proto::tag::subscript
383 , list2
<expr
&, typename
result_of::as_child
<A
>::type
>
388 proto::tag::subscript
389 , list2
<expr
&, typename
result_of::as_child
<A
>::type
>
390 > that
= {*this, proto::as_child(a
)};
398 proto::tag::subscript
399 , list2
<expr
&, typename
result_of::as_child
<A
const>::type
>
401 operator [](A
const &a
)
404 proto::tag::subscript
405 , list2
<expr
&, typename
result_of::as_child
<A
const>::type
>
406 > that
= {*this, proto::as_child(a
)};
411 /// Encodes the return type of \c expr\<\>::operator(), for use with \c boost::result_of\<\>
413 template<typename Sig
>
416 typedef typename
result_of::funop
<Sig
, expr
, default_domain
>::type
const type
;
421 /// \return A new \c expr\<\> node representing the function invocation of \c (*this)().
422 proto::expr
<proto::tag::function
, list1
<expr
const &> > const
425 proto::expr
<proto::tag::function
, list1
<expr
const &> > that
= {*this};
432 proto::expr
<proto::tag::function
, list1
<expr
&> > const
435 proto::expr
<proto::tag::function
, list1
<expr
&> > that
= {*this};
440 #define BOOST_PP_ITERATION_PARAMS_2 (3, (1, BOOST_PP_DEC(BOOST_PROTO_MAX_FUNCTION_CALL_ARITY), <boost/proto/expr.hpp>))
441 #include BOOST_PP_ITERATE()
447 #elif BOOST_PP_ITERATION_DEPTH() == 2
449 #define N BOOST_PP_ITERATION()
453 template<BOOST_PP_ENUM_PARAMS(N
, typename A
)>
454 typename
result_of::BOOST_PP_CAT(funop
, N
)<
456 , default_domain
BOOST_PP_ENUM_TRAILING_PARAMS(N
, const A
)
458 operator ()(BOOST_PP_ENUM_BINARY_PARAMS(N
, A
, const &a
)) const
460 return result_of::BOOST_PP_CAT(funop
, N
)<
462 , default_domain
BOOST_PP_ENUM_TRAILING_PARAMS(N
, const A
)
463 >::call(*this BOOST_PP_ENUM_TRAILING_PARAMS(N
, a
));
469 template<BOOST_PP_ENUM_PARAMS(N
, typename A
)>
470 typename
result_of::BOOST_PP_CAT(funop
, N
)<
472 , default_domain
BOOST_PP_ENUM_TRAILING_PARAMS(N
, const A
)
474 operator ()(BOOST_PP_ENUM_BINARY_PARAMS(N
, A
, const &a
))
476 return result_of::BOOST_PP_CAT(funop
, N
)<
478 , default_domain
BOOST_PP_ENUM_TRAILING_PARAMS(N
, const A
)
479 >::call(*this BOOST_PP_ENUM_TRAILING_PARAMS(N
, a
));
485 #endif // BOOST_PP_ITERATION_DEPTH()