~twpol/dcplusplus/trunk

« back to all changes in this revision

Viewing changes to boost/boost/proto/transform/make.hpp

  • Committer: James Ross
  • Date: 2010-07-05 00:03:18 UTC
  • mfrom: (1524.1.650 dcplusplus)
  • Revision ID: silver@warwickcompsoc.co.uk-20100705000318-awwqm8ocpp5m47yz
Merged to trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#ifndef BOOST_PP_IS_ITERATING
2
 
    ///////////////////////////////////////////////////////////////////////////////
3
 
    /// \file make.hpp
4
 
    /// Contains definition of the make<> transform.
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)
9
 
 
10
 
    #ifndef BOOST_PROTO_TRANSFORM_MAKE_HPP_EAN_12_02_2007
11
 
    #define BOOST_PROTO_TRANSFORM_MAKE_HPP_EAN_12_02_2007
12
 
 
13
 
    #include <boost/proto/detail/prefix.hpp>
14
 
    #include <boost/detail/workaround.hpp>
15
 
    #include <boost/preprocessor/repetition/enum.hpp>
16
 
    #include <boost/preprocessor/repetition/enum_params.hpp>
17
 
    #include <boost/preprocessor/repetition/enum_trailing_params.hpp>
18
 
    #include <boost/preprocessor/repetition/enum_binary_params.hpp>
19
 
    #include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
20
 
    #include <boost/preprocessor/repetition/repeat_from_to.hpp>
21
 
    #include <boost/preprocessor/facilities/intercept.hpp>
22
 
    #include <boost/preprocessor/cat.hpp>
23
 
    #include <boost/preprocessor/iteration/iterate.hpp>
24
 
    #include <boost/preprocessor/selection/max.hpp>
25
 
    #include <boost/preprocessor/arithmetic/inc.hpp>
26
 
    #include <boost/mpl/aux_/has_type.hpp>
27
 
    #include <boost/mpl/aux_/template_arity.hpp>
28
 
    #include <boost/mpl/aux_/lambda_arity_param.hpp>
29
 
    #include <boost/utility/result_of.hpp>
30
 
    #include <boost/type_traits/remove_const.hpp>
31
 
    #include <boost/type_traits/remove_reference.hpp>
32
 
    #include <boost/proto/proto_fwd.hpp>
33
 
    #include <boost/proto/traits.hpp>
34
 
    #include <boost/proto/args.hpp>
35
 
    #include <boost/proto/transform/impl.hpp>
36
 
    #include <boost/proto/detail/as_lvalue.hpp>
37
 
    #include <boost/proto/detail/ignore_unused.hpp>
38
 
    #include <boost/proto/detail/suffix.hpp>
39
 
 
40
 
    namespace boost { namespace proto
41
 
    {
42
 
        namespace detail
43
 
        {
44
 
            template<BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(BOOST_PROTO_MAX_ARITY, typename A, void)>
45
 
            struct typelist
46
 
            {
47
 
                typedef void type;
48
 
            };
49
 
 
50
 
            template<typename T, bool HasType = mpl::aux::has_type<T>::value>
51
 
            struct nested_type
52
 
            {
53
 
                typedef typename T::type type;
54
 
            };
55
 
 
56
 
            template<typename T>
57
 
            struct nested_type<T, false>
58
 
            {
59
 
                typedef T type;
60
 
            };
61
 
 
62
 
            template<typename T, typename Args, typename Void = void>
63
 
            struct nested_type_if
64
 
              : nested_type<T>
65
 
            {};
66
 
 
67
 
            template<typename R, typename Expr, typename State, typename Data
68
 
                , bool IsTransform = is_callable<R>::value
69
 
            >
70
 
            struct make_if_;
71
 
 
72
 
            template<typename R, typename Expr, typename State, typename Data
73
 
                BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(long Arity = mpl::aux::template_arity<R>::value)
74
 
            >
75
 
            struct make_
76
 
            {
77
 
                typedef R type;
78
 
                typedef void not_applied_;
79
 
            };
80
 
 
81
 
            template<typename R, typename Expr, typename State, typename Data>
82
 
            struct make_if_<R, Expr, State, Data, false>
83
 
              : make_<R, Expr, State, Data>
84
 
            {};
85
 
 
86
 
            #if BOOST_WORKAROUND(__GNUC__, == 3) || (__GNUC__ == 4 && __GNUC_MINOR__ == 0)
87
 
            // work around GCC bug
88
 
            template<typename Tag, typename Args, long N, typename Expr, typename State, typename Data>
89
 
            struct make_if_<proto::expr<Tag, Args, N>, Expr, State, Data, false>
90
 
            {
91
 
                typedef proto::expr<Tag, Args, N> type;
92
 
                typedef void not_applied_;
93
 
            };
94
 
            #endif
95
 
 
96
 
            // TODO could optimize this if R is a transform
97
 
            template<typename R, typename Expr, typename State, typename Data>
98
 
            struct make_if_<R, Expr, State, Data, true>
99
 
              : remove_const<typename remove_reference<
100
 
                    typename boost::result_of<R(Expr, State, Data)>::type
101
 
                >::type>
102
 
            {};
103
 
 
104
 
            template<typename Type, bool IsAggregate = is_aggregate<Type>::value>
105
 
            struct construct_
106
 
            {
107
 
                typedef Type result_type;
108
 
 
109
 
                Type operator ()() const
110
 
                {
111
 
                    return Type();
112
 
                }
113
 
 
114
 
                #define TMP(Z, N, DATA)                                                             \
115
 
                template<BOOST_PP_ENUM_PARAMS_Z(Z, N, typename A)>                                  \
116
 
                Type operator ()(BOOST_PP_ENUM_BINARY_PARAMS_Z(Z, N, A, &a)) const                  \
117
 
                {                                                                                   \
118
 
                    return Type(BOOST_PP_ENUM_PARAMS_Z(Z, N, a));                                   \
119
 
                }
120
 
                BOOST_PP_REPEAT_FROM_TO(1, BOOST_PP_INC(BOOST_PROTO_MAX_ARITY), TMP, ~)
121
 
                #undef TMP
122
 
            };
123
 
 
124
 
            template<typename Type>
125
 
            struct construct_<Type, true>
126
 
            {
127
 
                typedef Type result_type;
128
 
 
129
 
                Type operator ()() const
130
 
                {
131
 
                    return Type();
132
 
                }
133
 
 
134
 
                #define TMP(Z, N, DATA)                                                             \
135
 
                template<BOOST_PP_ENUM_PARAMS_Z(Z, N, typename A)>                                  \
136
 
                Type operator ()(BOOST_PP_ENUM_BINARY_PARAMS_Z(Z, N, A, &a)) const                  \
137
 
                {                                                                                   \
138
 
                    Type that = {BOOST_PP_ENUM_PARAMS_Z(Z, N, a)};                                  \
139
 
                    return that;                                                                    \
140
 
                }
141
 
                BOOST_PP_REPEAT_FROM_TO(1, BOOST_PP_INC(BOOST_PROTO_MAX_ARITY), TMP, ~)
142
 
                #undef TMP
143
 
            };
144
 
 
145
 
            #define TMP(Z, N, DATA)                                                                 \
146
 
            template<typename Type BOOST_PP_ENUM_TRAILING_PARAMS_Z(Z, N, typename A)>               \
147
 
            Type construct(BOOST_PP_ENUM_BINARY_PARAMS_Z(Z, N, A, &a))                              \
148
 
            {                                                                                       \
149
 
                return construct_<Type>()(BOOST_PP_ENUM_PARAMS_Z(Z, N, a));                         \
150
 
            }
151
 
            BOOST_PP_REPEAT(BOOST_PROTO_MAX_ARITY, TMP, ~)
152
 
            #undef TMP
153
 
        }
154
 
 
155
 
        /// \brief A PrimitiveTransform which prevents another PrimitiveTransform
156
 
        /// from being applied in an \c ObjectTransform.
157
 
        ///
158
 
        /// When building higher order transforms with <tt>make\<\></tt> or
159
 
        /// <tt>lazy\<\></tt>, you sometimes would like to build types that
160
 
        /// are parameterized with Proto transforms. In such lambda-style
161
 
        /// transforms, Proto will unhelpfully find all nested transforms
162
 
        /// and apply them, even if you don't want them to be applied. Consider
163
 
        /// the following transform, which will replace the \c _ in
164
 
        /// <tt>Bar<_>()</tt> with <tt>proto::terminal\<int\>::type</tt>:
165
 
        ///
166
 
        /// \code
167
 
        /// template<typename T>
168
 
        /// struct Bar
169
 
        /// {};
170
 
        /// 
171
 
        /// struct Foo
172
 
        ///   : proto::when<_, Bar<_>() >
173
 
        /// {};
174
 
        /// 
175
 
        /// proto::terminal<int>::type i = {0};
176
 
        /// 
177
 
        /// int main()
178
 
        /// {
179
 
        ///     Foo()(i);
180
 
        ///     std::cout << typeid(Foo()(i)).name() << std::endl;
181
 
        /// }
182
 
        /// \endcode
183
 
        ///
184
 
        /// If you actually wanted to default-construct an object of type
185
 
        /// <tt>Bar\<_\></tt>, you would have to protect the \c _ to prevent
186
 
        /// it from being applied. You can use <tt>proto::protect\<\></tt>
187
 
        /// as follows:
188
 
        ///
189
 
        /// \code
190
 
        /// // OK: replace anything with Bar<_>()
191
 
        /// struct Foo
192
 
        ///   : proto::when<_, Bar<protect<_> >() >
193
 
        /// {};
194
 
        /// \endcode
195
 
        template<typename PrimitiveTransform>
196
 
        struct protect : transform<protect<PrimitiveTransform> >
197
 
        {
198
 
            template<typename, typename, typename>
199
 
            struct impl
200
 
            {
201
 
                typedef PrimitiveTransform result_type;
202
 
            };
203
 
        };
204
 
 
205
 
        /// \brief A PrimitiveTransform which computes a type by evaluating any
206
 
        /// nested transforms and then constructs an object of that type.
207
 
        ///
208
 
        /// The <tt>make\<\></tt> transform checks to see if \c Object is a template.
209
 
        /// If it is, the template type is disassembled to find nested transforms.
210
 
        /// Proto considers the following types to represent transforms:
211
 
        ///
212
 
        /// \li Function types
213
 
        /// \li Function pointer types
214
 
        /// \li Types for which <tt>proto::is_callable\< type \>::::value</tt> is \c true
215
 
        ///
216
 
        /// <tt>make\<T\<X0,X1,...\> \>::::result\<void(Expr, State, Data)\>::::type</tt>
217
 
        /// is evaluated as follows. For each \c X in <tt>X0,X1,...</tt>, do:
218
 
        ///
219
 
        /// \li If \c X is a template like <tt>U\<Y0,Y1,...\></tt>, then let <tt>X'</tt>
220
 
        ///     be <tt>make\<U\<Y0,Y1,...\> \>::::result\<void(Expr, State, Data)\>::::type</tt>
221
 
        ///     (which evaluates this procedure recursively). Note whether any
222
 
        ///     substitutions took place during this operation.
223
 
        /// \li Otherwise, if \c X is a transform, then let <tt>X'</tt> be
224
 
        ///     <tt>when\<_, X\>::::result\<void(Expr, State, Data)\>::::type</tt>.
225
 
        ///     Note that a substitution took place.
226
 
        /// \li Otherwise, let <tt>X'</tt> be \c X, and note that no substitution
227
 
        ///     took place.
228
 
        /// \li If any substitutions took place in any of the above steps and
229
 
        ///     <tt>T\<X0',X1',...\></tt> has a nested <tt>::type</tt> typedef,
230
 
        ///     the result type is <tt>T\<X0',X1',...\>::::type</tt>.
231
 
        /// \li Otherwise, the result type is <tt>T\<X0',X1',...\></tt>.
232
 
        ///
233
 
        /// Note that <tt>when\<\></tt> is implemented in terms of <tt>call\<\></tt>
234
 
        /// and <tt>make\<\></tt>, so the above procedure is evaluated recursively.
235
 
        template<typename Object>
236
 
        struct make : transform<make<Object> >
237
 
        {
238
 
            template<typename Expr, typename State, typename Data>
239
 
            struct impl : transform_impl<Expr, State, Data>
240
 
            {
241
 
                typedef typename detail::make_if_<Object, Expr, State, Data>::type result_type;
242
 
 
243
 
                /// \return <tt>result_type()</tt>
244
 
                result_type operator ()(
245
 
                    typename impl::expr_param
246
 
                  , typename impl::state_param
247
 
                  , typename impl::data_param
248
 
                ) const
249
 
                {
250
 
                    return result_type();
251
 
                }
252
 
            };
253
 
        };
254
 
 
255
 
        #define BOOST_PP_ITERATION_PARAMS_1 (3, (0, BOOST_PROTO_MAX_ARITY, <boost/proto/transform/make.hpp>))
256
 
        #include BOOST_PP_ITERATE()
257
 
 
258
 
        /// INTERNAL ONLY
259
 
        ///
260
 
        template<typename Object>
261
 
        struct is_callable<make<Object> >
262
 
          : mpl::true_
263
 
        {};
264
 
 
265
 
        /// INTERNAL ONLY
266
 
        ///
267
 
        template<typename PrimitiveTransform>
268
 
        struct is_callable<protect<PrimitiveTransform> >
269
 
          : mpl::true_
270
 
        {};
271
 
    }}
272
 
 
273
 
    #endif
274
 
 
275
 
#else
276
 
 
277
 
    #define N BOOST_PP_ITERATION()
278
 
 
279
 
        namespace detail
280
 
        {
281
 
            #if N > 0
282
 
            template<typename T BOOST_PP_ENUM_TRAILING_PARAMS(N, typename A)>
283
 
            struct nested_type_if<
284
 
                T
285
 
              , typelist<BOOST_PP_ENUM_PARAMS(N, A)>
286
 
              , typename typelist<
287
 
                    BOOST_PP_ENUM_BINARY_PARAMS(N, typename A, ::not_applied_ BOOST_PP_INTERCEPT)
288
 
                >::type
289
 
            >
290
 
            {
291
 
                typedef T type;
292
 
                typedef void not_applied_;
293
 
            };
294
 
 
295
 
            template<
296
 
                template<BOOST_PP_ENUM_PARAMS(N, typename BOOST_PP_INTERCEPT)> class R
297
 
                BOOST_PP_ENUM_TRAILING_PARAMS(N, typename A)
298
 
              , typename Expr, typename State, typename Data
299
 
            >
300
 
            struct make_<R<BOOST_PP_ENUM_PARAMS(N, A)>, Expr, State, Data
301
 
                BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(N)
302
 
            >
303
 
              : nested_type_if<
304
 
                    #define TMP0(Z, M, DATA) make_if_<BOOST_PP_CAT(A, M), Expr, State, Data>
305
 
                    #define TMP1(Z, M, DATA) typename TMP0(Z, M, DATA) ::type
306
 
                    R<BOOST_PP_ENUM(N, TMP1, ~)>
307
 
                  , typelist<BOOST_PP_ENUM(N, TMP0, ~) >
308
 
                    #undef TMP0
309
 
                    #undef TMP1
310
 
                >
311
 
            {};
312
 
            #endif
313
 
 
314
 
            template<
315
 
                typename R
316
 
                BOOST_PP_ENUM_TRAILING_PARAMS(N, typename A)
317
 
              , typename Expr, typename State, typename Data
318
 
            >
319
 
            struct make_if_<R(BOOST_PP_ENUM_PARAMS(N, A)), Expr, State, Data, false>
320
 
            {
321
 
                typedef
322
 
                    typename remove_const<
323
 
                        typename remove_reference<
324
 
                            typename when<_, R(BOOST_PP_ENUM_PARAMS(N, A))>
325
 
                                ::template impl<Expr, State, Data>::result_type
326
 
                        >::type
327
 
                    >::type
328
 
                type;
329
 
            };
330
 
 
331
 
            template<
332
 
                typename R
333
 
                BOOST_PP_ENUM_TRAILING_PARAMS(N, typename A)
334
 
              , typename Expr, typename State, typename Data
335
 
            >
336
 
            struct make_if_<R(*)(BOOST_PP_ENUM_PARAMS(N, A)), Expr, State, Data, false>
337
 
            {
338
 
                typedef
339
 
                    typename remove_const<
340
 
                        typename remove_reference<
341
 
                            typename when<_, R(BOOST_PP_ENUM_PARAMS(N, A))>
342
 
                                ::template impl<Expr, State, Data>::result_type
343
 
                        >::type
344
 
                    >::type
345
 
                type;
346
 
            };
347
 
 
348
 
            template<typename T, typename A>
349
 
            struct construct_<proto::expr<T, A, N>, true>
350
 
            {
351
 
                typedef proto::expr<T, A, N> result_type;
352
 
 
353
 
                template<BOOST_PP_ENUM_PARAMS(BOOST_PP_MAX(N, 1), typename A)>
354
 
                result_type operator ()(BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_MAX(N, 1), A, &a)) const
355
 
                {
356
 
                    return result_type::make(BOOST_PP_ENUM_PARAMS(BOOST_PP_MAX(N, 1), a));
357
 
                }
358
 
            };
359
 
        }
360
 
 
361
 
        /// \brief A PrimitiveTransform which computes a type by evaluating any
362
 
        /// nested transforms and then constructs an object of that type with the
363
 
        /// current expression, state and data, transformed according
364
 
        /// to \c A0 through \c AN.
365
 
        template<typename Object BOOST_PP_ENUM_TRAILING_PARAMS(N, typename A)>
366
 
        struct make<Object(BOOST_PP_ENUM_PARAMS(N, A))>
367
 
          : transform<make<Object(BOOST_PP_ENUM_PARAMS(N, A))> >
368
 
        {
369
 
            template<typename Expr, typename State, typename Data>
370
 
            struct impl : transform_impl<Expr, State, Data>
371
 
            {
372
 
                /// \brief <tt>make\<Object\>::::result\<void(Expr, State, Data)\>::::type</tt>
373
 
                typedef typename detail::make_if_<Object, Expr, State, Data>::type result_type;
374
 
                //typedef typename detail::make_<Object, Expr, State, Data>::type result_type;
375
 
 
376
 
                /// Let \c ax be <tt>when\<_, Ax\>()(e, s, d)</tt>
377
 
                /// for each \c x in <tt>[0,N]</tt>.
378
 
                /// Let \c T be <tt>result\<void(Expr, State, Data)\>::::type</tt>.
379
 
                /// Return <tt>T(a0, a1,... aN)</tt>.
380
 
                ///
381
 
                /// \param e The current expression
382
 
                /// \param s The current state
383
 
                /// \param d An arbitrary data
384
 
                result_type operator ()(
385
 
                    typename impl::expr_param   e
386
 
                  , typename impl::state_param  s
387
 
                  , typename impl::data_param   d
388
 
                ) const
389
 
                {
390
 
                    proto::detail::ignore_unused(e);
391
 
                    proto::detail::ignore_unused(s);
392
 
                    proto::detail::ignore_unused(d);
393
 
                    return detail::construct<result_type>(
394
 
                        #define TMP(Z, M, DATA)                                                     \
395
 
                            detail::as_lvalue(                                                      \
396
 
                                typename when<_, BOOST_PP_CAT(A, M)>                                \
397
 
                                    ::template impl<Expr, State, Data>()(e, s, d)         \
398
 
                            )
399
 
                        BOOST_PP_ENUM(N, TMP, DATA)
400
 
                        #undef TMP
401
 
                    );
402
 
                }
403
 
            };
404
 
        };
405
 
 
406
 
        #if BOOST_WORKAROUND(__GNUC__, == 3) || (__GNUC__ == 4 && __GNUC_MINOR__ == 0)
407
 
        // work around GCC bug
408
 
        template<typename Tag, typename Args, long Arity BOOST_PP_ENUM_TRAILING_PARAMS(N, typename A)>
409
 
        struct make<proto::expr<Tag, Args, Arity>(BOOST_PP_ENUM_PARAMS(N, A))>
410
 
          : transform<make<proto::expr<Tag, Args, Arity>(BOOST_PP_ENUM_PARAMS(N, A))> >
411
 
        {
412
 
            template<typename Expr, typename State, typename Data>
413
 
            struct impl : transform_impl<Expr, State, Data>
414
 
            {
415
 
                typedef proto::expr<Tag, Args, Arity> result_type;
416
 
 
417
 
                result_type operator ()(
418
 
                    typename impl::expr_param   e
419
 
                  , typename impl::state_param  s
420
 
                  , typename impl::data_param   d
421
 
                ) const
422
 
                {
423
 
                    return proto::expr<Tag, Args, Arity>::make(
424
 
                        #define TMP(Z, M, DATA)                                                     \
425
 
                            detail::as_lvalue(                                                      \
426
 
                                typename when<_, BOOST_PP_CAT(A, M)>                                \
427
 
                                    ::template impl<Expr, State, Data>()(e, s, d)         \
428
 
                            )
429
 
                        BOOST_PP_ENUM(N, TMP, DATA)
430
 
                        #undef TMP
431
 
                    );
432
 
                }
433
 
            };
434
 
        };
435
 
        #endif
436
 
 
437
 
    #undef N
438
 
 
439
 
#endif
 
1
#ifndef BOOST_PP_IS_ITERATING
 
2
    ///////////////////////////////////////////////////////////////////////////////
 
3
    /// \file make.hpp
 
4
    /// Contains definition of the make<> transform.
 
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)
 
9
 
 
10
    #ifndef BOOST_PROTO_TRANSFORM_MAKE_HPP_EAN_12_02_2007
 
11
    #define BOOST_PROTO_TRANSFORM_MAKE_HPP_EAN_12_02_2007
 
12
 
 
13
    #include <boost/proto/detail/prefix.hpp>
 
14
    #include <boost/detail/workaround.hpp>
 
15
    #include <boost/preprocessor/repetition/enum.hpp>
 
16
    #include <boost/preprocessor/repetition/enum_params.hpp>
 
17
    #include <boost/preprocessor/repetition/enum_trailing_params.hpp>
 
18
    #include <boost/preprocessor/repetition/enum_binary_params.hpp>
 
19
    #include <boost/preprocessor/repetition/enum_params_with_a_default.hpp>
 
20
    #include <boost/preprocessor/repetition/repeat_from_to.hpp>
 
21
    #include <boost/preprocessor/facilities/intercept.hpp>
 
22
    #include <boost/preprocessor/cat.hpp>
 
23
    #include <boost/preprocessor/iteration/iterate.hpp>
 
24
    #include <boost/preprocessor/selection/max.hpp>
 
25
    #include <boost/preprocessor/arithmetic/inc.hpp>
 
26
    #include <boost/mpl/aux_/has_type.hpp>
 
27
    #include <boost/mpl/aux_/template_arity.hpp>
 
28
    #include <boost/mpl/aux_/lambda_arity_param.hpp>
 
29
    #include <boost/utility/result_of.hpp>
 
30
    #include <boost/type_traits/remove_const.hpp>
 
31
    #include <boost/type_traits/remove_reference.hpp>
 
32
    #include <boost/proto/proto_fwd.hpp>
 
33
    #include <boost/proto/traits.hpp>
 
34
    #include <boost/proto/args.hpp>
 
35
    #include <boost/proto/transform/impl.hpp>
 
36
    #include <boost/proto/detail/as_lvalue.hpp>
 
37
    #include <boost/proto/detail/ignore_unused.hpp>
 
38
    #include <boost/proto/detail/suffix.hpp>
 
39
 
 
40
    namespace boost { namespace proto
 
41
    {
 
42
        namespace detail
 
43
        {
 
44
            template<BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(BOOST_PROTO_MAX_ARITY, typename A, void)>
 
45
            struct typelist
 
46
            {
 
47
                typedef void type;
 
48
            };
 
49
 
 
50
            template<typename T, bool HasType = mpl::aux::has_type<T>::value>
 
51
            struct nested_type
 
52
            {
 
53
                typedef typename T::type type;
 
54
            };
 
55
 
 
56
            template<typename T>
 
57
            struct nested_type<T, false>
 
58
            {
 
59
                typedef T type;
 
60
            };
 
61
 
 
62
            template<typename T, typename Args, typename Void = void>
 
63
            struct nested_type_if
 
64
              : nested_type<T>
 
65
            {};
 
66
 
 
67
            template<typename R, typename Expr, typename State, typename Data
 
68
                // BUGBUG this should be is_transform, but if R is a template instantiation
 
69
                // it will cause the template to be instantiated, whereas is_callable will not.
 
70
              , bool IsTransform = is_callable<R>::value
 
71
            >
 
72
            struct make_if_;
 
73
 
 
74
            template<typename R, typename Expr, typename State, typename Data
 
75
                BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(long Arity = mpl::aux::template_arity<R>::value)
 
76
            >
 
77
            struct make_
 
78
            {
 
79
                typedef R type;
 
80
                typedef void not_applied_;
 
81
            };
 
82
 
 
83
            template<typename R, typename Expr, typename State, typename Data>
 
84
            struct make_if_<R, Expr, State, Data, false>
 
85
              : make_<R, Expr, State, Data>
 
86
            {};
 
87
 
 
88
            #if BOOST_WORKAROUND(__GNUC__, == 3) || (__GNUC__ == 4 && __GNUC_MINOR__ == 0)
 
89
            // work around GCC bug
 
90
            template<typename Tag, typename Args, long N, typename Expr, typename State, typename Data>
 
91
            struct make_if_<proto::expr<Tag, Args, N>, Expr, State, Data, false>
 
92
            {
 
93
                typedef proto::expr<Tag, Args, N> type;
 
94
                typedef void not_applied_;
 
95
            };
 
96
            #endif
 
97
 
 
98
            // TODO could optimize this if R is a transform
 
99
            template<typename R, typename Expr, typename State, typename Data>
 
100
            struct make_if_<R, Expr, State, Data, true>
 
101
              : remove_const<
 
102
                    typename remove_reference<
 
103
                        typename R::template impl<Expr, State, Data>::result_type
 
104
                    >::type
 
105
                >
 
106
            {};
 
107
 
 
108
            template<typename Type, bool IsAggregate = is_aggregate<Type>::value>
 
109
            struct construct_
 
110
            {
 
111
                typedef Type result_type;
 
112
 
 
113
                Type operator ()() const
 
114
                {
 
115
                    return Type();
 
116
                }
 
117
 
 
118
                #define TMP(Z, N, DATA)                                                             \
 
119
                template<BOOST_PP_ENUM_PARAMS_Z(Z, N, typename A)>                                  \
 
120
                Type operator ()(BOOST_PP_ENUM_BINARY_PARAMS_Z(Z, N, A, &a)) const                  \
 
121
                {                                                                                   \
 
122
                    return Type(BOOST_PP_ENUM_PARAMS_Z(Z, N, a));                                   \
 
123
                }
 
124
                BOOST_PP_REPEAT_FROM_TO(1, BOOST_PP_INC(BOOST_PROTO_MAX_ARITY), TMP, ~)
 
125
                #undef TMP
 
126
            };
 
127
 
 
128
            template<typename Type>
 
129
            struct construct_<Type, true>
 
130
            {
 
131
                typedef Type result_type;
 
132
 
 
133
                Type operator ()() const
 
134
                {
 
135
                    return Type();
 
136
                }
 
137
 
 
138
                #define TMP(Z, N, DATA)                                                             \
 
139
                template<BOOST_PP_ENUM_PARAMS_Z(Z, N, typename A)>                                  \
 
140
                Type operator ()(BOOST_PP_ENUM_BINARY_PARAMS_Z(Z, N, A, &a)) const                  \
 
141
                {                                                                                   \
 
142
                    Type that = {BOOST_PP_ENUM_PARAMS_Z(Z, N, a)};                                  \
 
143
                    return that;                                                                    \
 
144
                }
 
145
                BOOST_PP_REPEAT_FROM_TO(1, BOOST_PP_INC(BOOST_PROTO_MAX_ARITY), TMP, ~)
 
146
                #undef TMP
 
147
            };
 
148
 
 
149
            #define TMP(Z, N, DATA)                                                                 \
 
150
            template<typename Type BOOST_PP_ENUM_TRAILING_PARAMS_Z(Z, N, typename A)>               \
 
151
            Type construct(BOOST_PP_ENUM_BINARY_PARAMS_Z(Z, N, A, &a))                              \
 
152
            {                                                                                       \
 
153
                return construct_<Type>()(BOOST_PP_ENUM_PARAMS_Z(Z, N, a));                         \
 
154
            }
 
155
            BOOST_PP_REPEAT(BOOST_PROTO_MAX_ARITY, TMP, ~)
 
156
            #undef TMP
 
157
        }
 
158
 
 
159
        /// \brief A PrimitiveTransform which prevents another PrimitiveTransform
 
160
        /// from being applied in an \c ObjectTransform.
 
161
        ///
 
162
        /// When building higher order transforms with <tt>make\<\></tt> or
 
163
        /// <tt>lazy\<\></tt>, you sometimes would like to build types that
 
164
        /// are parameterized with Proto transforms. In such lambda-style
 
165
        /// transforms, Proto will unhelpfully find all nested transforms
 
166
        /// and apply them, even if you don't want them to be applied. Consider
 
167
        /// the following transform, which will replace the \c _ in
 
168
        /// <tt>Bar<_>()</tt> with <tt>proto::terminal\<int\>::type</tt>:
 
169
        ///
 
170
        /// \code
 
171
        /// template<typename T>
 
172
        /// struct Bar
 
173
        /// {};
 
174
        /// 
 
175
        /// struct Foo
 
176
        ///   : proto::when<_, Bar<_>() >
 
177
        /// {};
 
178
        /// 
 
179
        /// proto::terminal<int>::type i = {0};
 
180
        /// 
 
181
        /// int main()
 
182
        /// {
 
183
        ///     Foo()(i);
 
184
        ///     std::cout << typeid(Foo()(i)).name() << std::endl;
 
185
        /// }
 
186
        /// \endcode
 
187
        ///
 
188
        /// If you actually wanted to default-construct an object of type
 
189
        /// <tt>Bar\<_\></tt>, you would have to protect the \c _ to prevent
 
190
        /// it from being applied. You can use <tt>proto::protect\<\></tt>
 
191
        /// as follows:
 
192
        ///
 
193
        /// \code
 
194
        /// // OK: replace anything with Bar<_>()
 
195
        /// struct Foo
 
196
        ///   : proto::when<_, Bar<protect<_> >() >
 
197
        /// {};
 
198
        /// \endcode
 
199
        template<typename PrimitiveTransform>
 
200
        struct protect : transform<protect<PrimitiveTransform> >
 
201
        {
 
202
            template<typename, typename, typename>
 
203
            struct impl
 
204
            {
 
205
                typedef PrimitiveTransform result_type;
 
206
            };
 
207
        };
 
208
 
 
209
        /// \brief A PrimitiveTransform which computes a type by evaluating any
 
210
        /// nested transforms and then constructs an object of that type.
 
211
        ///
 
212
        /// The <tt>make\<\></tt> transform checks to see if \c Object is a template.
 
213
        /// If it is, the template type is disassembled to find nested transforms.
 
214
        /// Proto considers the following types to represent transforms:
 
215
        ///
 
216
        /// \li Function types
 
217
        /// \li Function pointer types
 
218
        /// \li Types for which <tt>proto::is_callable\< type \>::::value</tt> is \c true
 
219
        ///
 
220
        /// <tt>boost::result_of\<make\<T\<X0,X1,...\> \>(Expr, State, Data)\>::::type</tt>
 
221
        /// is evaluated as follows. For each \c X in <tt>X0,X1,...</tt>, do:
 
222
        ///
 
223
        /// \li If \c X is a template like <tt>U\<Y0,Y1,...\></tt>, then let <tt>X'</tt>
 
224
        ///     be <tt>boost::result_of\<make\<U\<Y0,Y1,...\> \>(Expr, State, Data)\>::::type</tt>
 
225
        ///     (which evaluates this procedure recursively). Note whether any
 
226
        ///     substitutions took place during this operation.
 
227
        /// \li Otherwise, if \c X is a transform, then let <tt>X'</tt> be
 
228
        ///     <tt>boost::result_of\<when\<_, X\>(Expr, State, Data)\>::::type</tt>.
 
229
        ///     Note that a substitution took place.
 
230
        /// \li Otherwise, let <tt>X'</tt> be \c X, and note that no substitution
 
231
        ///     took place.
 
232
        /// \li If any substitutions took place in any of the above steps and
 
233
        ///     <tt>T\<X0',X1',...\></tt> has a nested <tt>::type</tt> typedef,
 
234
        ///     the result type is <tt>T\<X0',X1',...\>::::type</tt>.
 
235
        /// \li Otherwise, the result type is <tt>T\<X0',X1',...\></tt>.
 
236
        ///
 
237
        /// Note that <tt>when\<\></tt> is implemented in terms of <tt>call\<\></tt>
 
238
        /// and <tt>make\<\></tt>, so the above procedure is evaluated recursively.
 
239
        template<typename Object>
 
240
        struct make : transform<make<Object> >
 
241
        {
 
242
            template<typename Expr, typename State, typename Data>
 
243
            struct impl : transform_impl<Expr, State, Data>
 
244
            {
 
245
                typedef typename detail::make_if_<Object, Expr, State, Data>::type result_type;
 
246
 
 
247
                /// \return <tt>result_type()</tt>
 
248
                result_type operator ()(
 
249
                    typename impl::expr_param
 
250
                  , typename impl::state_param
 
251
                  , typename impl::data_param
 
252
                ) const
 
253
                {
 
254
                    return result_type();
 
255
                }
 
256
            };
 
257
        };
 
258
 
 
259
        #define BOOST_PP_ITERATION_PARAMS_1 (3, (0, BOOST_PROTO_MAX_ARITY, <boost/proto/transform/make.hpp>))
 
260
        #include BOOST_PP_ITERATE()
 
261
 
 
262
        /// INTERNAL ONLY
 
263
        ///
 
264
        template<typename Object>
 
265
        struct is_callable<make<Object> >
 
266
          : mpl::true_
 
267
        {};
 
268
 
 
269
        /// INTERNAL ONLY
 
270
        ///
 
271
        template<typename PrimitiveTransform>
 
272
        struct is_callable<protect<PrimitiveTransform> >
 
273
          : mpl::true_
 
274
        {};
 
275
    }}
 
276
 
 
277
    #endif
 
278
 
 
279
#else
 
280
 
 
281
    #define N BOOST_PP_ITERATION()
 
282
 
 
283
        namespace detail
 
284
        {
 
285
            #if N > 0
 
286
            template<typename T BOOST_PP_ENUM_TRAILING_PARAMS(N, typename A)>
 
287
            struct nested_type_if<
 
288
                T
 
289
              , typelist<BOOST_PP_ENUM_PARAMS(N, A)>
 
290
              , typename typelist<
 
291
                    BOOST_PP_ENUM_BINARY_PARAMS(N, typename A, ::not_applied_ BOOST_PP_INTERCEPT)
 
292
                >::type
 
293
            >
 
294
            {
 
295
                typedef T type;
 
296
                typedef void not_applied_;
 
297
            };
 
298
 
 
299
            #define TMP0(Z, M, DATA) make_if_<BOOST_PP_CAT(A, M), Expr, State, Data>
 
300
            #define TMP1(Z, M, DATA) typename TMP0(Z, M, DATA) ::type
 
301
 
 
302
            template<
 
303
                template<BOOST_PP_ENUM_PARAMS(N, typename BOOST_PP_INTERCEPT)> class R
 
304
                BOOST_PP_ENUM_TRAILING_PARAMS(N, typename A)
 
305
              , typename Expr, typename State, typename Data
 
306
            >
 
307
            struct make_<R<BOOST_PP_ENUM_PARAMS(N, A)>, Expr, State, Data
 
308
                BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(N)
 
309
            >
 
310
              : nested_type_if<
 
311
                    R<BOOST_PP_ENUM(N, TMP1, ~)>
 
312
                  , typelist<BOOST_PP_ENUM(N, TMP0, ~) >
 
313
                >
 
314
            {};
 
315
 
 
316
            template<
 
317
                template<BOOST_PP_ENUM_PARAMS(N, typename BOOST_PP_INTERCEPT)> class R
 
318
                BOOST_PP_ENUM_TRAILING_PARAMS(N, typename A)
 
319
              , typename Expr, typename State, typename Data
 
320
            >
 
321
            struct make_<noinvoke<R<BOOST_PP_ENUM_PARAMS(N, A)> >, Expr, State, Data
 
322
                BOOST_MPL_AUX_LAMBDA_ARITY_PARAM(N)
 
323
            >
 
324
            {
 
325
                typedef R<BOOST_PP_ENUM(N, TMP1, ~)> type;
 
326
            };
 
327
 
 
328
            #undef TMP0
 
329
            #undef TMP1
 
330
            #endif
 
331
 
 
332
            template<
 
333
                typename R
 
334
                BOOST_PP_ENUM_TRAILING_PARAMS(N, typename A)
 
335
              , typename Expr, typename State, typename Data
 
336
            >
 
337
            struct make_if_<R(BOOST_PP_ENUM_PARAMS(N, A)), Expr, State, Data, false>
 
338
            {
 
339
                typedef
 
340
                    typename remove_const<
 
341
                        typename remove_reference<
 
342
                            typename when<_, R(BOOST_PP_ENUM_PARAMS(N, A))>
 
343
                                ::template impl<Expr, State, Data>::result_type
 
344
                        >::type
 
345
                    >::type
 
346
                type;
 
347
            };
 
348
 
 
349
            template<
 
350
                typename R
 
351
                BOOST_PP_ENUM_TRAILING_PARAMS(N, typename A)
 
352
              , typename Expr, typename State, typename Data
 
353
            >
 
354
            struct make_if_<R(*)(BOOST_PP_ENUM_PARAMS(N, A)), Expr, State, Data, false>
 
355
            {
 
356
                typedef
 
357
                    typename remove_const<
 
358
                        typename remove_reference<
 
359
                            typename when<_, R(BOOST_PP_ENUM_PARAMS(N, A))>
 
360
                                ::template impl<Expr, State, Data>::result_type
 
361
                        >::type
 
362
                    >::type
 
363
                type;
 
364
            };
 
365
 
 
366
            template<typename T, typename A>
 
367
            struct construct_<proto::expr<T, A, N>, true>
 
368
            {
 
369
                typedef proto::expr<T, A, N> result_type;
 
370
 
 
371
                template<BOOST_PP_ENUM_PARAMS(BOOST_PP_MAX(N, 1), typename A)>
 
372
                result_type operator ()(BOOST_PP_ENUM_BINARY_PARAMS(BOOST_PP_MAX(N, 1), A, &a)) const
 
373
                {
 
374
                    return result_type::make(BOOST_PP_ENUM_PARAMS(BOOST_PP_MAX(N, 1), a));
 
375
                }
 
376
            };
 
377
        }
 
378
 
 
379
        /// \brief A PrimitiveTransform which computes a type by evaluating any
 
380
        /// nested transforms and then constructs an object of that type with the
 
381
        /// current expression, state and data, transformed according
 
382
        /// to \c A0 through \c AN.
 
383
        template<typename Object BOOST_PP_ENUM_TRAILING_PARAMS(N, typename A)>
 
384
        struct make<Object(BOOST_PP_ENUM_PARAMS(N, A))>
 
385
          : transform<make<Object(BOOST_PP_ENUM_PARAMS(N, A))> >
 
386
        {
 
387
            template<typename Expr, typename State, typename Data>
 
388
            struct impl : transform_impl<Expr, State, Data>
 
389
            {
 
390
                /// \brief <tt>boost::result_of\<make\<Object\>(Expr, State, Data)\>::::type</tt>
 
391
                typedef typename detail::make_if_<Object, Expr, State, Data>::type result_type;
 
392
                //typedef typename detail::make_<Object, Expr, State, Data>::type result_type;
 
393
 
 
394
                /// Let \c ax be <tt>when\<_, Ax\>()(e, s, d)</tt>
 
395
                /// for each \c x in <tt>[0,N]</tt>.
 
396
                /// Return <tt>result_type(a0, a1,... aN)</tt>.
 
397
                ///
 
398
                /// \param e The current expression
 
399
                /// \param s The current state
 
400
                /// \param d An arbitrary data
 
401
                result_type operator ()(
 
402
                    typename impl::expr_param   e
 
403
                  , typename impl::state_param  s
 
404
                  , typename impl::data_param   d
 
405
                ) const
 
406
                {
 
407
                    proto::detail::ignore_unused(e);
 
408
                    proto::detail::ignore_unused(s);
 
409
                    proto::detail::ignore_unused(d);
 
410
                    return detail::construct<result_type>(
 
411
                        #define TMP(Z, M, DATA)                                                     \
 
412
                            detail::as_lvalue(                                                      \
 
413
                                typename when<_, BOOST_PP_CAT(A, M)>                                \
 
414
                                    ::template impl<Expr, State, Data>()(e, s, d)         \
 
415
                            )
 
416
                        BOOST_PP_ENUM(N, TMP, DATA)
 
417
                        #undef TMP
 
418
                    );
 
419
                }
 
420
            };
 
421
        };
 
422
 
 
423
        #if BOOST_WORKAROUND(__GNUC__, == 3) || (__GNUC__ == 4 && __GNUC_MINOR__ == 0)
 
424
        // work around GCC bug
 
425
        template<typename Tag, typename Args, long Arity BOOST_PP_ENUM_TRAILING_PARAMS(N, typename A)>
 
426
        struct make<proto::expr<Tag, Args, Arity>(BOOST_PP_ENUM_PARAMS(N, A))>
 
427
          : transform<make<proto::expr<Tag, Args, Arity>(BOOST_PP_ENUM_PARAMS(N, A))> >
 
428
        {
 
429
            template<typename Expr, typename State, typename Data>
 
430
            struct impl : transform_impl<Expr, State, Data>
 
431
            {
 
432
                typedef proto::expr<Tag, Args, Arity> result_type;
 
433
 
 
434
                result_type operator ()(
 
435
                    typename impl::expr_param   e
 
436
                  , typename impl::state_param  s
 
437
                  , typename impl::data_param   d
 
438
                ) const
 
439
                {
 
440
                    return proto::expr<Tag, Args, Arity>::make(
 
441
                        #define TMP(Z, M, DATA)                                                     \
 
442
                            detail::as_lvalue(                                                      \
 
443
                                typename when<_, BOOST_PP_CAT(A, M)>                                \
 
444
                                    ::template impl<Expr, State, Data>()(e, s, d)         \
 
445
                            )
 
446
                        BOOST_PP_ENUM(N, TMP, DATA)
 
447
                        #undef TMP
 
448
                    );
 
449
                }
 
450
            };
 
451
        };
 
452
        #endif
 
453
 
 
454
    #undef N
 
455
 
 
456
#endif