1 #if !defined(BOOST_PROTO_DONT_USE_PREPROCESSED_FILES)
2 
3     #ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES
4         #include <boost/proto/detail/preprocessed/expr_variadic.hpp>
5     #else
6         #include <boost/proto/detail/preprocessed/expr.hpp>
7     #endif
8 
9 #elif !defined(BOOST_PP_IS_ITERATING)
10 
11     /// INTERNAL ONLY
12     ///
13     #define BOOST_PROTO_CHILD(Z, N, DATA)                                                       \
14         typedef BOOST_PP_CAT(Arg, N) BOOST_PP_CAT(proto_child, N);                              \
15         BOOST_PP_CAT(proto_child, N) BOOST_PP_CAT(child, N);                                    \
16         /**< INTERNAL ONLY */
17 
18     /// INTERNAL ONLY
19     ///
20     #define BOOST_PROTO_VOID(Z, N, DATA)                                                        \
21         typedef void BOOST_PP_CAT(proto_child, N);                                              \
22         /**< INTERNAL ONLY */
23 
24     // Generate variadic versions of expr
25     #if defined(__WAVE__) && defined(BOOST_PROTO_CREATE_PREPROCESSED_FILES)
26         #pragma wave option(preserve: 2, line: 0, output: "preprocessed/expr_variadic.hpp")
27     #endif
28 
29     ///////////////////////////////////////////////////////////////////////////////
30     /// \file expr_variadic.hpp
31     /// Contains definition of expr\<\> class template.
32     //
33     //  Copyright 2008 Eric Niebler. Distributed under the Boost
34     //  Software License, Version 1.0. (See accompanying file
35     //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
36 
37     #if defined(__WAVE__) && defined(BOOST_PROTO_CREATE_PREPROCESSED_FILES)
38         #pragma wave option(preserve: 1)
39     #endif
40 
41     // The expr<> specializations are actually defined here.
42     #define BOOST_PROTO_DEFINE_TERMINAL
43     #define BOOST_PP_ITERATION_PARAMS_1                                                         \
44         (3, (0, 0, <boost/proto/detail/expr.hpp>))
45     #include BOOST_PP_ITERATE()
46 
47     #undef BOOST_PROTO_DEFINE_TERMINAL
48     #define BOOST_PP_ITERATION_PARAMS_1                                                         \
49         (3, (1, BOOST_PROTO_MAX_ARITY, <boost/proto/detail/expr.hpp>))
50     #include BOOST_PP_ITERATE()
51 
52     // Generate non-variadic versions of expr
53     #if defined(__WAVE__) && defined(BOOST_PROTO_CREATE_PREPROCESSED_FILES)
54         #define BOOST_NO_CXX11_VARIADIC_TEMPLATES
55         #pragma wave option(preserve: 2, line: 0, output: "preprocessed/expr.hpp")
56 
57         ///////////////////////////////////////////////////////////////////////////////
58         /// \file expr.hpp
59         /// Contains definition of expr\<\> class template.
60         //
61         //  Copyright 2008 Eric Niebler. Distributed under the Boost
62         //  Software License, Version 1.0. (See accompanying file
63         //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
64 
65         #pragma wave option(preserve: 1)
66 
67         // The expr<> specializations are actually defined here.
68         #define BOOST_PROTO_DEFINE_TERMINAL
69         #define BOOST_PP_ITERATION_PARAMS_1 (3, (0, 0, <boost/proto/detail/expr.hpp>))
70         #include BOOST_PP_ITERATE()
71 
72         #undef BOOST_PROTO_DEFINE_TERMINAL
73         #define BOOST_PP_ITERATION_PARAMS_1 (3, (1, BOOST_PROTO_MAX_ARITY, <boost/proto/detail/expr.hpp>))
74         #include BOOST_PP_ITERATE()
75 
76         #pragma wave option(output: null)
77         #undef BOOST_NO_CXX11_VARIADIC_TEMPLATES
78     #endif
79 
80     #undef BOOST_PROTO_CHILD
81     #undef BOOST_PROTO_VOID
82 
83 #else
84 
85     #define ARG_COUNT BOOST_PP_MAX(1, BOOST_PP_ITERATION())
86 
87     /// \brief Representation of a node in an expression tree.
88     ///
89     /// \c proto::expr\<\> is a node in an expression template tree. It
90     /// is a container for its child sub-trees. It also serves as
91     /// the terminal nodes of the tree.
92     ///
93     /// \c Tag is type that represents the operation encoded by
94     ///             this expression. It is typically one of the structs
95     ///             in the \c boost::proto::tag namespace, but it doesn't
96     ///             have to be.
97     ///
98     /// \c Args is a type list representing the type of the children
99     ///             of this expression. It is an instantiation of one
100     ///             of \c proto::list1\<\>, \c proto::list2\<\>, etc. The
101     ///             child types must all themselves be either \c expr\<\>
102     ///             or <tt>proto::expr\<\>&</tt>. If \c Args is an
103     ///             instantiation of \c proto::term\<\> then this
104     ///             \c expr\<\> type represents a terminal expression;
105     ///             the parameter to the \c proto::term\<\> template
106     ///             represents the terminal's value type.
107     ///
108     /// \c Arity is an integral constant representing the number of child
109     ///             nodes this node contains. If \c Arity is 0, then this
110     ///             node is a terminal.
111     ///
112     /// \c proto::expr\<\> is a valid Fusion random-access sequence, where
113     /// the elements of the sequence are the child expressions.
114     #ifdef BOOST_PROTO_DEFINE_TERMINAL
115     template<typename Tag, typename Arg0>
116     struct expr<Tag, term<Arg0>, 0>
117     #else
118     template<typename Tag BOOST_PP_ENUM_TRAILING_PARAMS(ARG_COUNT, typename Arg)>
119     struct expr<Tag, BOOST_PP_CAT(list, BOOST_PP_ITERATION())<BOOST_PP_ENUM_PARAMS(ARG_COUNT, Arg)>, BOOST_PP_ITERATION() >
120     #endif
121     {
122         typedef Tag proto_tag;
123         static const long proto_arity_c = BOOST_PP_ITERATION();
124         typedef mpl::long_<BOOST_PP_ITERATION() > proto_arity;
125         typedef expr proto_base_expr;
126         #ifdef BOOST_PROTO_DEFINE_TERMINAL
127         typedef term<Arg0> proto_args;
128         #else
129         typedef BOOST_PP_CAT(list, BOOST_PP_ITERATION())<BOOST_PP_ENUM_PARAMS(ARG_COUNT, Arg)> proto_args;
130         #endif
131         typedef basic_expr<Tag, proto_args, BOOST_PP_ITERATION() > proto_grammar;
132         typedef default_domain proto_domain;
133         typedef default_generator proto_generator;
134         typedef proto::tag::proto_expr<Tag, proto_domain> fusion_tag;
135         typedef expr proto_derived_expr;
136         typedef void proto_is_expr_; /**< INTERNAL ONLY */
137 
138         BOOST_PP_REPEAT(ARG_COUNT, BOOST_PROTO_CHILD, ~)
139         BOOST_PP_REPEAT_FROM_TO(ARG_COUNT, BOOST_PROTO_MAX_ARITY, BOOST_PROTO_VOID, ~)
140 
141         /// \return *this
142         ///
143         BOOST_FORCEINLINE
proto_baseexpr144         expr const &proto_base() const
145         {
146             return *this;
147         }
148 
149         /// \overload
150         ///
151         BOOST_FORCEINLINE
proto_baseexpr152         expr &proto_base()
153         {
154             return *this;
155         }
156 
157     #ifdef BOOST_PROTO_DEFINE_TERMINAL
158         /// \return A new \c expr\<\> object initialized with the specified
159         /// arguments.
160         ///
161         template<typename A0>
162         BOOST_FORCEINLINE
makeexpr163         static expr const make(A0 &a0)
164         {
165             return detail::make_terminal(a0, static_cast<expr *>(0), static_cast<proto_args *>(0));
166         }
167 
168         /// \overload
169         ///
170         template<typename A0>
171         BOOST_FORCEINLINE
makeexpr172         static expr const make(A0 const &a0)
173         {
174             return detail::make_terminal(a0, static_cast<expr *>(0), static_cast<proto_args *>(0));
175         }
176     #else
177         /// \return A new \c expr\<\> object initialized with the specified
178         /// arguments.
179         ///
180         template<BOOST_PP_ENUM_PARAMS(ARG_COUNT, typename A)>
181         BOOST_FORCEINLINE
makeexpr182         static expr const make(BOOST_PP_ENUM_BINARY_PARAMS(ARG_COUNT, A, const &a))
183         {
184             expr that = {BOOST_PP_ENUM_PARAMS(ARG_COUNT, a)};
185             return that;
186         }
187     #endif
188 
189     #if 1 == BOOST_PP_ITERATION()
190         /// If \c Tag is \c boost::proto::tag::address_of and \c proto_child0 is
191         /// <tt>T&</tt>, then \c address_of_hack_type_ is <tt>T*</tt>.
192         /// Otherwise, it is some undefined type.
193         typedef typename detail::address_of_hack<Tag, proto_child0>::type address_of_hack_type_;
194 
195         /// \return The address of <tt>this->child0</tt> if \c Tag is
196         /// \c boost::proto::tag::address_of. Otherwise, this function will
197         /// fail to compile.
198         ///
199         /// \attention Proto overloads <tt>operator&</tt>, which means that
200         /// proto-ified objects cannot have their addresses taken, unless we use
201         /// the following hack to make \c &x implicitly convertible to \c X*.
202         BOOST_FORCEINLINE
operator address_of_hack_type_expr203         operator address_of_hack_type_() const
204         {
205             return boost::addressof(this->child0);
206         }
207     #else
208         /// INTERNAL ONLY
209         ///
210         typedef detail::not_a_valid_type address_of_hack_type_;
211     #endif
212 
213         /// Assignment
214         ///
215         /// \param a The rhs.
216         /// \return A new \c expr\<\> node representing an assignment of \c that to \c *this.
217         BOOST_FORCEINLINE
218         proto::expr<
219             proto::tag::assign
220           , list2<expr &, expr const &>
221           , 2
222         > const
operator =expr223         operator =(expr const &a)
224         {
225             proto::expr<
226                 proto::tag::assign
227               , list2<expr &, expr const &>
228               , 2
229             > that = {*this, a};
230             return that;
231         }
232 
233         /// Assignment
234         ///
235         /// \param a The rhs.
236         /// \return A new \c expr\<\> node representing an assignment of \c a to \c *this.
237         template<typename A>
238         BOOST_FORCEINLINE
239         proto::expr<
240             proto::tag::assign
241           , list2<expr const &, typename result_of::as_child<A>::type>
242           , 2
243         > const
operator =expr244         operator =(A &a) const
245         {
246             proto::expr<
247                 proto::tag::assign
248               , list2<expr const &, typename result_of::as_child<A>::type>
249               , 2
250             > that = {*this, proto::as_child(a)};
251             return that;
252         }
253 
254         /// \overload
255         ///
256         template<typename A>
257         BOOST_FORCEINLINE
258         proto::expr<
259             proto::tag::assign
260           , list2<expr const &, typename result_of::as_child<A const>::type>
261           , 2
262         > const
operator =expr263         operator =(A const &a) const
264         {
265             proto::expr<
266                 proto::tag::assign
267               , list2<expr const &, typename result_of::as_child<A const>::type>
268               , 2
269             > that = {*this, proto::as_child(a)};
270             return that;
271         }
272 
273     #ifdef BOOST_PROTO_DEFINE_TERMINAL
274         /// \overload
275         ///
276         template<typename A>
277         BOOST_FORCEINLINE
278         proto::expr<
279             proto::tag::assign
280           , list2<expr &, typename result_of::as_child<A>::type>
281           , 2
282         > const
operator =expr283         operator =(A &a)
284         {
285             proto::expr<
286                 proto::tag::assign
287               , list2<expr &, typename result_of::as_child<A>::type>
288               , 2
289             > that = {*this, proto::as_child(a)};
290             return that;
291         }
292 
293         /// \overload
294         ///
295         template<typename A>
296         BOOST_FORCEINLINE
297         proto::expr<
298             proto::tag::assign
299           , list2<expr &, typename result_of::as_child<A const>::type>
300           , 2
301         > const
operator =expr302         operator =(A const &a)
303         {
304             proto::expr<
305                 proto::tag::assign
306               , list2<expr &, typename result_of::as_child<A const>::type>
307               , 2
308             > that = {*this, proto::as_child(a)};
309             return that;
310         }
311     #endif
312 
313         /// Subscript
314         ///
315         /// \param a The rhs.
316         /// \return A new \c expr\<\> node representing \c *this subscripted with \c a.
317         template<typename A>
318         BOOST_FORCEINLINE
319         proto::expr<
320             proto::tag::subscript
321           , list2<expr const &, typename result_of::as_child<A>::type>
322           , 2
323         > const
operator []expr324         operator [](A &a) const
325         {
326             proto::expr<
327                 proto::tag::subscript
328               , list2<expr const &, typename result_of::as_child<A>::type>
329               , 2
330             > that = {*this, proto::as_child(a)};
331             return that;
332         }
333 
334         /// \overload
335         ///
336         template<typename A>
337         BOOST_FORCEINLINE
338         proto::expr<
339             proto::tag::subscript
340           , list2<expr const &, typename result_of::as_child<A const>::type>
341           , 2
342         > const
operator []expr343         operator [](A const &a) const
344         {
345             proto::expr<
346                 proto::tag::subscript
347               , list2<expr const &, typename result_of::as_child<A const>::type>
348               , 2
349             > that = {*this, proto::as_child(a)};
350             return that;
351         }
352 
353     #ifdef BOOST_PROTO_DEFINE_TERMINAL
354         /// \overload
355         ///
356         template<typename A>
357         BOOST_FORCEINLINE
358         proto::expr<
359             proto::tag::subscript
360           , list2<expr &, typename result_of::as_child<A>::type>
361           , 2
362         > const
operator []expr363         operator [](A &a)
364         {
365             proto::expr<
366                 proto::tag::subscript
367               , list2<expr &, typename result_of::as_child<A>::type>
368               , 2
369             > that = {*this, proto::as_child(a)};
370             return that;
371         }
372 
373         /// \overload
374         ///
375         template<typename A>
376         BOOST_FORCEINLINE
377         proto::expr<
378             proto::tag::subscript
379           , list2<expr &, typename result_of::as_child<A const>::type>
380           , 2
381         > const
operator []expr382         operator [](A const &a)
383         {
384             proto::expr<
385                 proto::tag::subscript
386               , list2<expr &, typename result_of::as_child<A const>::type>
387               , 2
388             > that = {*this, proto::as_child(a)};
389             return that;
390         }
391     #endif
392 
393         /// Encodes the return type of \c expr\<\>::operator(), for use with \c boost::result_of\<\>
394         ///
395         template<typename Sig>
396         struct result
397         {
398             typedef typename result_of::funop<Sig, expr, default_domain>::type const type;
399         };
400 
401     #ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES
402         /// \overload
403         ///
404         template<typename ...A>
405         BOOST_FORCEINLINE
406         typename result_of::funop<
407             expr const(A const &...)
408           , expr
409           , default_domain
410         >::type const
operator ()expr411         operator ()(A const &... a) const
412         {
413             return result_of::funop<
414                 expr const(A const &...)
415               , expr
416               , default_domain
417             >::call(*this, a...);
418         }
419 
420     #ifdef BOOST_PROTO_DEFINE_TERMINAL
421         /// \overload
422         ///
423         template<typename ...A>
424         BOOST_FORCEINLINE
425         typename result_of::funop<
426             expr(A const &...)
427           , expr
428           , default_domain
429         >::type const
operator ()expr430         operator ()(A const &... a)
431         {
432             return result_of::funop<
433                 expr(A const &...)
434               , expr
435               , default_domain
436             >::call(*this, a...);
437         }
438     #endif
439 
440     #else // BOOST_NO_CXX11_VARIADIC_TEMPLATES
441 
442         /// Function call
443         ///
444         /// \return A new \c expr\<\> node representing the function invocation of \c (*this)().
445         BOOST_FORCEINLINE
446         proto::expr<proto::tag::function, list1<expr const &>, 1> const
operator ()expr447         operator ()() const
448         {
449             proto::expr<proto::tag::function, list1<expr const &>, 1> that = {*this};
450             return that;
451         }
452 
453     #ifdef BOOST_PROTO_DEFINE_TERMINAL
454         /// \overload
455         ///
456         BOOST_FORCEINLINE
457         proto::expr<proto::tag::function, list1<expr &>, 1> const
operator ()expr458         operator ()()
459         {
460             proto::expr<proto::tag::function, list1<expr &>, 1> that = {*this};
461             return that;
462         }
463     #endif
464 
465     #define BOOST_PP_ITERATION_PARAMS_2                                                             \
466         (3, (1, BOOST_PP_DEC(BOOST_PROTO_MAX_FUNCTION_CALL_ARITY), <boost/proto/detail/expr_funop.hpp>))
467     #include BOOST_PP_ITERATE()
468 
469 #endif
470     };
471 
472 #undef ARG_COUNT
473 
474 #endif
475