fix doc example typo
[boost.git] / boost / proto / expr.hpp
blob8a48098f51227ee7d17e712d57d9fa14c4af2d3f
1 #ifndef BOOST_PP_IS_ITERATING
2 ///////////////////////////////////////////////////////////////////////////////
3 /// \file expr.hpp
4 /// Contains definition of expr\<\> class template.
5 //
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
36 #endif
38 namespace boost { namespace proto
41 namespace detail
43 /// INTERNAL ONLY
44 ///
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); \
48 /**< INTERNAL ONLY */
50 /// INTERNAL ONLY
51 ///
52 #define BOOST_PROTO_VOID(Z, N, DATA) \
53 typedef void BOOST_PP_CAT(proto_child, N); \
54 /**< INTERNAL ONLY */
56 struct not_a_valid_type
58 private:
59 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 &>
72 typedef Expr *type;
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)
80 y[i] = x[i];
84 template<typename T, std::size_t N>
85 struct if_is_array
86 {};
88 template<typename T, std::size_t N>
89 struct if_is_array<T[N], N>
91 typedef int type;
96 namespace result_of
98 /// \brief A helper metafunction for computing the
99 /// return type of \c proto::expr\<\>::operator().
100 template<typename Sig, typename This, typename Domain>
101 struct funop;
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
125 /// expression.
126 template<typename Expr>
127 struct unexpr
128 : Expr
130 BOOST_PROTO_UNEXPR()
132 explicit unexpr(Expr const &expr)
133 : Expr(expr)
136 using Expr::operator =;
141 #if defined(_MSC_VER) && (_MSC_VER >= 1020)
142 # pragma warning(pop)
143 #endif
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
164 /// have to be.
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, ~)
198 /// \return *this
200 expr const &proto_base() const
202 return *this;
205 /// \overload
207 expr &proto_base()
209 return *this;
212 /// \return A new \c expr\<\> object initialized with the specified
213 /// arguments.
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)};
219 return that;
222 #if IS_TERMINAL
223 /// \overload
225 template<typename A0>
226 static expr const make(A0 &a0)
228 expr that = {a0};
229 return that;
232 /// \overload
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)
237 expr that;
238 detail::checked_copy(a0, that.child0);
239 return that;
242 /// \overload
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)
247 expr that;
248 detail::checked_copy(a0, that.child0);
249 return that;
251 #endif
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
261 /// fail to compile.
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);
270 #else
271 /// INTERNAL ONLY
273 typedef detail::not_a_valid_type address_of_hack_type_;
274 #endif
276 /// Assignment
278 /// \param a The rhs.
279 /// \return A new \c expr\<\> node representing an assignment of \c a to \c *this.
280 template<typename A>
281 proto::expr<
282 proto::tag::assign
283 , list2<expr const &, typename result_of::as_child<A>::type>
284 > const
285 operator =(A &a) const
287 proto::expr<
288 proto::tag::assign
289 , list2<expr const &, typename result_of::as_child<A>::type>
290 > that = {*this, proto::as_child(a)};
291 return that;
294 /// \overload
296 template<typename A>
297 proto::expr<
298 proto::tag::assign
299 , list2<expr const &, typename result_of::as_child<A const>::type>
300 > const
301 operator =(A const &a) const
303 proto::expr<
304 proto::tag::assign
305 , list2<expr const &, typename result_of::as_child<A const>::type>
306 > that = {*this, proto::as_child(a)};
307 return that;
310 #if IS_TERMINAL
311 /// \overload
313 template<typename A>
314 proto::expr<
315 proto::tag::assign
316 , list2<expr &, typename result_of::as_child<A>::type>
317 > const
318 operator =(A &a)
320 proto::expr<
321 proto::tag::assign
322 , list2<expr &, typename result_of::as_child<A>::type>
323 > that = {*this, proto::as_child(a)};
324 return that;
327 /// \overload
329 template<typename A>
330 proto::expr<
331 proto::tag::assign
332 , list2<expr &, typename result_of::as_child<A const>::type>
333 > const
334 operator =(A const &a)
336 proto::expr<
337 proto::tag::assign
338 , list2<expr &, typename result_of::as_child<A const>::type>
339 > that = {*this, proto::as_child(a)};
340 return that;
342 #endif
344 /// Subscript
346 /// \param a The rhs.
347 /// \return A new \c expr\<\> node representing \c *this subscripted with \c a.
348 template<typename A>
349 proto::expr<
350 proto::tag::subscript
351 , list2<expr const &, typename result_of::as_child<A>::type>
352 > const
353 operator [](A &a) const
355 proto::expr<
356 proto::tag::subscript
357 , list2<expr const &, typename result_of::as_child<A>::type>
358 > that = {*this, proto::as_child(a)};
359 return that;
362 /// \overload
364 template<typename A>
365 proto::expr<
366 proto::tag::subscript
367 , list2<expr const &, typename result_of::as_child<A const>::type> > const
368 operator [](A const &a) const
370 proto::expr<
371 proto::tag::subscript
372 , list2<expr const &, typename result_of::as_child<A const>::type>
373 > that = {*this, proto::as_child(a)};
374 return that;
377 #if IS_TERMINAL
378 /// \overload
380 template<typename A>
381 proto::expr<
382 proto::tag::subscript
383 , list2<expr &, typename result_of::as_child<A>::type>
384 > const
385 operator [](A &a)
387 proto::expr<
388 proto::tag::subscript
389 , list2<expr &, typename result_of::as_child<A>::type>
390 > that = {*this, proto::as_child(a)};
391 return that;
394 /// \overload
396 template<typename A>
397 proto::expr<
398 proto::tag::subscript
399 , list2<expr &, typename result_of::as_child<A const>::type>
400 > const
401 operator [](A const &a)
403 proto::expr<
404 proto::tag::subscript
405 , list2<expr &, typename result_of::as_child<A const>::type>
406 > that = {*this, proto::as_child(a)};
407 return that;
409 #endif
411 /// Encodes the return type of \c expr\<\>::operator(), for use with \c boost::result_of\<\>
413 template<typename Sig>
414 struct result
416 typedef typename result_of::funop<Sig, expr, default_domain>::type const type;
419 /// Function call
421 /// \return A new \c expr\<\> node representing the function invocation of \c (*this)().
422 proto::expr<proto::tag::function, list1<expr const &> > const
423 operator ()() const
425 proto::expr<proto::tag::function, list1<expr const &> > that = {*this};
426 return that;
429 #if IS_TERMINAL
430 /// \overload
432 proto::expr<proto::tag::function, list1<expr &> > const
433 operator ()()
435 proto::expr<proto::tag::function, list1<expr &> > that = {*this};
436 return that;
438 #endif
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()
444 #undef ARG_COUNT
445 #undef IS_TERMINAL
447 #elif BOOST_PP_ITERATION_DEPTH() == 2
449 #define N BOOST_PP_ITERATION()
451 /// \overload
453 template<BOOST_PP_ENUM_PARAMS(N, typename A)>
454 typename result_of::BOOST_PP_CAT(funop, N)<
455 expr const
456 , default_domain BOOST_PP_ENUM_TRAILING_PARAMS(N, const A)
457 >::type const
458 operator ()(BOOST_PP_ENUM_BINARY_PARAMS(N, A, const &a)) const
460 return result_of::BOOST_PP_CAT(funop, N)<
461 expr const
462 , default_domain BOOST_PP_ENUM_TRAILING_PARAMS(N, const A)
463 >::call(*this BOOST_PP_ENUM_TRAILING_PARAMS(N, a));
466 #if IS_TERMINAL
467 /// \overload
469 template<BOOST_PP_ENUM_PARAMS(N, typename A)>
470 typename result_of::BOOST_PP_CAT(funop, N)<
471 expr
472 , default_domain BOOST_PP_ENUM_TRAILING_PARAMS(N, const A)
473 >::type const
474 operator ()(BOOST_PP_ENUM_BINARY_PARAMS(N, A, const &a))
476 return result_of::BOOST_PP_CAT(funop, N)<
477 expr
478 , default_domain BOOST_PP_ENUM_TRAILING_PARAMS(N, const A)
479 >::call(*this BOOST_PP_ENUM_TRAILING_PARAMS(N, a));
481 #endif
483 #undef N
485 #endif // BOOST_PP_ITERATION_DEPTH()
486 #endif