PageRenderTime 26ms CodeModel.GetById 10ms app.highlight 11ms RepoModel.GetById 1ms app.codeStats 0ms

/Src/Dependencies/Boost/boost/proto/extends.hpp

http://hadesmem.googlecode.com/
C++ Header | 627 lines | 444 code | 61 blank | 122 comment | 1 complexity | d6c78481a090dc9667d9e9d9903d9e48 MD5 | raw file
  1///////////////////////////////////////////////////////////////////////////////
  2/// \file extends.hpp
  3/// Macros and a base class for defining end-user expression types
  4//
  5//  Copyright 2008 Eric Niebler. Distributed under the Boost
  6//  Software License, Version 1.0. (See accompanying file
  7//  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  8
  9#ifndef BOOST_PROTO_EXTENDS_HPP_EAN_11_1_2006
 10#define BOOST_PROTO_EXTENDS_HPP_EAN_11_1_2006
 11
 12#include <cstddef> // for offsetof
 13#include <boost/config.hpp>
 14#include <boost/detail/workaround.hpp>
 15#include <boost/preprocessor/facilities/empty.hpp>
 16#include <boost/preprocessor/tuple/elem.hpp>
 17#include <boost/preprocessor/control/if.hpp>
 18#include <boost/preprocessor/arithmetic/inc.hpp>
 19#include <boost/preprocessor/arithmetic/dec.hpp>
 20#include <boost/preprocessor/iteration/local.hpp>
 21#include <boost/preprocessor/repetition/enum_params.hpp>
 22#include <boost/preprocessor/repetition/repeat_from_to.hpp>
 23#include <boost/preprocessor/repetition/enum_binary_params.hpp>
 24#include <boost/preprocessor/repetition/enum_trailing_params.hpp>
 25#include <boost/preprocessor/repetition/enum_trailing_binary_params.hpp>
 26#include <boost/preprocessor/seq/for_each.hpp>
 27#include <boost/utility/addressof.hpp>
 28#include <boost/utility/result_of.hpp>
 29#include <boost/proto/proto_fwd.hpp>
 30#include <boost/proto/traits.hpp>
 31#include <boost/proto/expr.hpp>
 32#include <boost/proto/args.hpp>
 33#include <boost/proto/traits.hpp>
 34#include <boost/proto/generate.hpp>
 35
 36#ifdef _MSC_VER
 37#define BOOST_PROTO_DISABLE_MSVC_C4522 __pragma(warning(disable: 4522))
 38#else
 39#define BOOST_PROTO_DISABLE_MSVC_C4522 
 40#endif
 41
 42namespace boost { namespace proto
 43{
 44    #ifdef __GNUC__
 45    /// INTERNAL ONLY
 46    ///
 47    # define BOOST_PROTO_ADDROF(x) ((char const volatile*)boost::addressof(x))
 48    /// INTERNAL ONLY
 49    ///
 50    # define BOOST_PROTO_OFFSETOF(s,m) (BOOST_PROTO_ADDROF((((s *)this)->m)) - BOOST_PROTO_ADDROF(*((s *)this)))
 51    #else
 52    /// INTERNAL ONLY
 53    ///
 54    # define BOOST_PROTO_OFFSETOF offsetof
 55    #endif
 56
 57    /// INTERNAL ONLY
 58    ///
 59    #define BOOST_PROTO_CONST() const
 60
 61    /// INTERNAL ONLY
 62    ///
 63    #define BOOST_PROTO_TYPENAME() typename
 64
 65    /// INTERNAL ONLY
 66    ///
 67    #define BOOST_PROTO_TEMPLATE_YES_(Z, N) template<BOOST_PP_ENUM_PARAMS_Z(Z, N, typename A)>
 68
 69    /// INTERNAL ONLY
 70    ///
 71    #define BOOST_PROTO_TEMPLATE_NO_(Z, N)
 72
 73    /// INTERNAL ONLY
 74    ///
 75    #define BOOST_PROTO_DEFINE_FUN_OP_IMPL_(Z, N, DATA, Const)                                      \
 76        BOOST_PP_IF(N, BOOST_PROTO_TEMPLATE_YES_, BOOST_PROTO_TEMPLATE_NO_)(Z, N)                   \
 77        typename BOOST_PROTO_RESULT_OF<                                                             \
 78            proto_generator(                                                                        \
 79                typename boost::proto::result_of::BOOST_PP_CAT(funop, N)<                           \
 80                    proto_derived_expr Const()                                                      \
 81                  , proto_domain                                                                    \
 82                    BOOST_PP_ENUM_TRAILING_PARAMS_Z(Z, N, const A)                                  \
 83                >::type                                                                             \
 84            )                                                                                       \
 85        >::type const                                                                               \
 86        operator ()(BOOST_PP_ENUM_BINARY_PARAMS_Z(Z, N, A, const &a)) Const()                       \
 87        {                                                                                           \
 88            typedef boost::proto::result_of::BOOST_PP_CAT(funop, N)<                                \
 89                proto_derived_expr Const()                                                          \
 90              , proto_domain                                                                        \
 91                BOOST_PP_ENUM_TRAILING_PARAMS_Z(Z, N, const A)                                      \
 92            > funop;                                                                                \
 93            return proto_generator()(                                                               \
 94                funop::call(                                                                        \
 95                    *static_cast<proto_derived_expr Const() *>(this)                                \
 96                    BOOST_PP_ENUM_TRAILING_PARAMS_Z(Z, N, a)                                        \
 97                )                                                                                   \
 98            );                                                                                      \
 99        }                                                                                           \
100        /**/
101
102    /// INTERNAL ONLY
103    ///
104    #define BOOST_PROTO_DEFINE_FUN_OP_VARIADIC_IMPL_(Const)                                         \
105        template<typename... A>                                                                     \
106        typename BOOST_PROTO_RESULT_OF<                                                             \
107            proto_generator(                                                                        \
108                typename boost::proto::result_of::funop<                                            \
109                    proto_derived_expr Const()(A const &...)                                        \
110                  , proto_derived_expr                                                              \
111                  , proto_domain                                                                    \
112                >::type                                                                             \
113            )                                                                                       \
114        >::type const                                                                               \
115        operator ()(A const &...a) Const()                                                          \
116        {                                                                                           \
117            typedef boost::proto::result_of::funop<                                                 \
118                proto_derived_expr Const()(A const &...)                                            \
119              , proto_derived_expr                                                                  \
120              , proto_domain                                                                        \
121            > funop;                                                                                \
122            return proto_generator()(                                                               \
123                funop::call(                                                                        \
124                    *static_cast<proto_derived_expr Const() *>(this)                                \
125                  , a...                                                                            \
126                )                                                                                   \
127            );                                                                                      \
128        }                                                                                           \
129        /**/
130
131    /// INTERNAL ONLY
132    ///
133    #define BOOST_PROTO_DEFINE_FUN_OP_CONST(Z, N, DATA)                                             \
134        BOOST_PROTO_DEFINE_FUN_OP_IMPL_(Z, N, DATA, BOOST_PROTO_CONST)                              \
135        /**/
136
137    /// INTERNAL ONLY
138    ///
139    #define BOOST_PROTO_DEFINE_FUN_OP_NON_CONST(Z, N, DATA)                                         \
140        BOOST_PROTO_DEFINE_FUN_OP_IMPL_(Z, N, DATA, BOOST_PP_EMPTY)                                 \
141        /**/
142
143    /// INTERNAL ONLY
144    ///
145    #define BOOST_PROTO_DEFINE_FUN_OP(Z, N, DATA)                                                   \
146        BOOST_PROTO_DEFINE_FUN_OP_CONST(Z, N, DATA)                                                 \
147        BOOST_PROTO_DEFINE_FUN_OP_NON_CONST(Z, N, DATA)                                             \
148        /**/
149
150    /// INTERNAL ONLY
151    ///
152    #define BOOST_PROTO_EXTENDS_CHILD(Z, N, DATA)                                                   \
153        typedef                                                                                     \
154            typename proto_base_expr::BOOST_PP_CAT(proto_child, N)                                  \
155        BOOST_PP_CAT(proto_child, N);                                                               \
156        /**/
157
158    #define BOOST_PROTO_BASIC_EXTENDS_(Expr, Derived, Domain)                                       \
159        Expr proto_expr_;                                                                           \
160                                                                                                    \
161        typedef Expr proto_base_expr_; /**< INTERNAL ONLY */                                        \
162        typedef typename proto_base_expr_::proto_base_expr proto_base_expr;                         \
163        typedef Domain proto_domain;                                                                \
164        typedef Derived proto_derived_expr;                                                         \
165        typedef typename proto_base_expr::proto_tag proto_tag;                                      \
166        typedef typename proto_base_expr::proto_args proto_args;                                    \
167        typedef typename proto_base_expr::proto_arity proto_arity;                                  \
168        typedef typename proto_base_expr::proto_grammar proto_grammar;                              \
169        typedef typename proto_base_expr::address_of_hack_type_ proto_address_of_hack_type_;        \
170        typedef void proto_is_expr_; /**< INTERNAL ONLY */                                          \
171        static const long proto_arity_c = proto_base_expr::proto_arity_c;                \
172        typedef boost::proto::tag::proto_expr fusion_tag;                                           \
173        BOOST_PP_REPEAT(BOOST_PROTO_MAX_ARITY, BOOST_PROTO_EXTENDS_CHILD, ~)                        \
174                                                                                                    \
175        static proto_derived_expr const make(Expr const &e)                                         \
176        {                                                                                           \
177            proto_derived_expr that = {e};                                                          \
178            return that;                                                                            \
179        }                                                                                           \
180                                                                                                    \
181        proto_base_expr &proto_base()                                                               \
182        {                                                                                           \
183            return this->proto_expr_.proto_base();                                                  \
184        }                                                                                           \
185                                                                                                    \
186        proto_base_expr const &proto_base() const                                                   \
187        {                                                                                           \
188            return this->proto_expr_.proto_base();                                                  \
189        }                                                                                           \
190                                                                                                    \
191        operator proto_address_of_hack_type_() const                                                \
192        {                                                                                           \
193            return boost::addressof(this->proto_base().child0);                                     \
194        }                                                                                           \
195        /**/
196
197    #define BOOST_PROTO_BASIC_EXTENDS(Expr, Derived, Domain)                                        \
198        BOOST_PROTO_BASIC_EXTENDS_(Expr, Derived, Domain)                                           \
199        typedef void proto_is_aggregate_;                                                           \
200        typedef Domain::proto_generator proto_generator;                                            \
201        /**< INTERNAL ONLY */
202
203    #define BOOST_PROTO_EXTENDS_COPY_ASSIGN_IMPL_(This, Const, Typename)                            \
204        BOOST_PROTO_DISABLE_MSVC_C4522                                                              \
205        Typename() BOOST_PROTO_RESULT_OF<                                                           \
206            Typename() This::proto_generator(                                                       \
207                Typename() boost::proto::base_expr<                                                 \
208                    Typename() This::proto_domain                                                   \
209                  , boost::proto::tag::assign                                                       \
210                  , boost::proto::list2<                                                            \
211                        This &                                                                      \
212                      , This Const() &                                                              \
213                    >                                                                               \
214                >::type                                                                             \
215            )                                                                                       \
216        >::type const                                                                               \
217        operator =(This Const() &a)                                                                 \
218        {                                                                                           \
219            typedef                                                                                 \
220                Typename() boost::proto::base_expr<                                                 \
221                    Typename() This::proto_domain                                                   \
222                  , boost::proto::tag::assign                                                       \
223                  , boost::proto::list2<                                                            \
224                        This &                                                                      \
225                      , This Const() &                                                              \
226                    >                                                                               \
227                >::type                                                                             \
228            that_type;                                                                              \
229            that_type const that = {                                                                \
230                *this                                                                               \
231              , a                                                                                   \
232            };                                                                                      \
233            return Typename() This::proto_generator()(that);                                        \
234        }                                                                                           \
235        /**/
236
237        // MSVC 8.0 and higher seem to need copy-assignment operator to be overloaded on *both*
238        // const and non-const rhs arguments.
239    #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1600)) && (BOOST_MSVC > 1310)
240        #define BOOST_PROTO_EXTENDS_COPY_ASSIGN_(This, Typename)                                    \
241            BOOST_PROTO_EXTENDS_COPY_ASSIGN_IMPL_(This, BOOST_PP_EMPTY, Typename)                   \
242            BOOST_PROTO_EXTENDS_COPY_ASSIGN_IMPL_(This, BOOST_PROTO_CONST, Typename)                \
243            /**/
244    #else
245        #define BOOST_PROTO_EXTENDS_COPY_ASSIGN_(This, Typename)                                    \
246            BOOST_PROTO_EXTENDS_COPY_ASSIGN_IMPL_(This, BOOST_PROTO_CONST, Typename)                \
247            /**/
248    #endif
249
250        /// INTERNAL ONLY
251        ///
252    #define BOOST_PROTO_EXTENDS_ASSIGN_IMPL_(ThisConst, ThatConst)                                  \
253        template<typename A>                                                                        \
254        typename BOOST_PROTO_RESULT_OF<                                                             \
255            proto_generator(                                                                        \
256                typename boost::proto::base_expr<                                                   \
257                    proto_domain                                                                    \
258                  , boost::proto::tag::assign                                                       \
259                  , boost::proto::list2<                                                            \
260                        proto_derived_expr ThisConst() &                                            \
261                      , typename boost::proto::result_of::as_child<A ThatConst(), proto_domain>::type \
262                    >                                                                               \
263                >::type                                                                             \
264            )                                                                                       \
265        >::type const                                                                               \
266        operator =(A ThatConst() &a) ThisConst()                                                    \
267        {                                                                                           \
268            typedef                                                                                 \
269                typename boost::proto::base_expr<                                                   \
270                    proto_domain                                                                    \
271                  , boost::proto::tag::assign                                                       \
272                  , boost::proto::list2<                                                            \
273                        proto_derived_expr ThisConst() &                                            \
274                      , typename boost::proto::result_of::as_child<A ThatConst(), proto_domain>::type \
275                    >                                                                               \
276                >::type                                                                             \
277            that_type;                                                                              \
278            that_type const that = {                                                                \
279                *static_cast<proto_derived_expr ThisConst() *>(this)                                \
280              , boost::proto::as_child<proto_domain>(a)                                             \
281            };                                                                                      \
282            return proto_generator()(that);                                                         \
283        }                                                                                           \
284        /**/
285
286    #define BOOST_PROTO_EXTENDS_ASSIGN_CONST_()                                                     \
287        BOOST_PROTO_EXTENDS_ASSIGN_IMPL_(BOOST_PROTO_CONST, BOOST_PP_EMPTY)                         \
288        BOOST_PROTO_EXTENDS_ASSIGN_IMPL_(BOOST_PROTO_CONST, BOOST_PROTO_CONST)                      \
289        /**/
290
291    #define BOOST_PROTO_EXTENDS_ASSIGN_NON_CONST_()                                                 \
292        BOOST_PROTO_EXTENDS_ASSIGN_IMPL_(BOOST_PP_EMPTY, BOOST_PP_EMPTY)                            \
293        BOOST_PROTO_EXTENDS_ASSIGN_IMPL_(BOOST_PP_EMPTY, BOOST_PROTO_CONST)                         \
294        /**/
295
296    #define BOOST_PROTO_EXTENDS_ASSIGN_()                                                           \
297        BOOST_PROTO_EXTENDS_ASSIGN_CONST_()                                                         \
298        BOOST_PROTO_EXTENDS_ASSIGN_NON_CONST_()                                                     \
299        /**/
300
301    #define BOOST_PROTO_EXTENDS_ASSIGN_CONST()                                                      \
302        BOOST_PROTO_EXTENDS_COPY_ASSIGN_(proto_derived_expr, BOOST_PROTO_TYPENAME)                  \
303        BOOST_PROTO_EXTENDS_ASSIGN_CONST_()                                                         \
304        /**/
305
306    #define BOOST_PROTO_EXTENDS_ASSIGN_NON_CONST()                                                  \
307        BOOST_PROTO_EXTENDS_COPY_ASSIGN_(proto_derived_expr, BOOST_PROTO_TYPENAME)                  \
308        BOOST_PROTO_EXTENDS_ASSIGN_NON_CONST_()                                                     \
309        /**/
310
311    #define BOOST_PROTO_EXTENDS_ASSIGN()                                                            \
312        BOOST_PROTO_EXTENDS_COPY_ASSIGN_(proto_derived_expr, BOOST_PROTO_TYPENAME)                  \
313        BOOST_PROTO_EXTENDS_ASSIGN_()                                                               \
314        /**/
315
316        /// INTERNAL ONLY
317        ///
318    #define BOOST_PROTO_EXTENDS_SUBSCRIPT_IMPL_(ThisConst, ThatConst)                               \
319        template<typename A>                                                                        \
320        typename BOOST_PROTO_RESULT_OF<                                                             \
321            proto_generator(                                                                        \
322                typename boost::proto::base_expr<                                                   \
323                    proto_domain                                                                    \
324                  , boost::proto::tag::subscript                                                    \
325                  , boost::proto::list2<                                                            \
326                        proto_derived_expr ThisConst() &                                            \
327                      , typename boost::proto::result_of::as_child<A ThatConst(), proto_domain>::type \
328                    >                                                                               \
329                >::type                                                                             \
330            )                                                                                       \
331        >::type const                                                                               \
332        operator [](A ThatConst() &a) ThisConst()                                                   \
333        {                                                                                           \
334            typedef                                                                                 \
335                typename boost::proto::base_expr<                                                   \
336                    proto_domain                                                                    \
337                  , boost::proto::tag::subscript                                                    \
338                  , boost::proto::list2<                                                            \
339                        proto_derived_expr ThisConst() &                                            \
340                      , typename boost::proto::result_of::as_child<A ThatConst(), proto_domain>::type \
341                    >                                                                               \
342                >::type                                                                             \
343            that_type;                                                                              \
344            that_type const that = {                                                                \
345                *static_cast<proto_derived_expr ThisConst() *>(this)                                \
346              , boost::proto::as_child<proto_domain>(a)                                             \
347            };                                                                                      \
348            return proto_generator()(that);                                                         \
349        }                                                                                           \
350        /**/
351
352    #define BOOST_PROTO_EXTENDS_SUBSCRIPT_CONST()                                                   \
353        BOOST_PROTO_EXTENDS_SUBSCRIPT_IMPL_(BOOST_PROTO_CONST, BOOST_PP_EMPTY)                      \
354        BOOST_PROTO_EXTENDS_SUBSCRIPT_IMPL_(BOOST_PROTO_CONST, BOOST_PROTO_CONST)                   \
355        /**/
356
357    #define BOOST_PROTO_EXTENDS_SUBSCRIPT_NON_CONST()                                               \
358        BOOST_PROTO_EXTENDS_SUBSCRIPT_IMPL_(BOOST_PP_EMPTY, BOOST_PP_EMPTY)                         \
359        BOOST_PROTO_EXTENDS_SUBSCRIPT_IMPL_(BOOST_PP_EMPTY, BOOST_PROTO_CONST)                      \
360        /**/
361
362    #define BOOST_PROTO_EXTENDS_SUBSCRIPT()                                                         \
363        BOOST_PROTO_EXTENDS_SUBSCRIPT_CONST()                                                       \
364        BOOST_PROTO_EXTENDS_SUBSCRIPT_NON_CONST()                                                   \
365        /**/
366
367        /// INTERNAL ONLY
368        ///
369    #define BOOST_PROTO_EXTENDS_FUNCTION_()                                                         \
370        template<typename Sig>                                                                      \
371        struct result                                                                               \
372        {                                                                                           \
373            typedef                                                                                 \
374                typename BOOST_PROTO_RESULT_OF<                                                     \
375                    proto_generator(                                                                \
376                        typename boost::proto::result_of::funop<                                    \
377                            Sig                                                                     \
378                          , proto_derived_expr                                                      \
379                          , proto_domain                                                            \
380                        >::type                                                                     \
381                    )                                                                               \
382                >::type const                                                                       \
383            type;                                                                                   \
384        };                                                                                          \
385        /**/
386
387    #ifndef BOOST_NO_VARIADIC_TEMPLATES
388        #define BOOST_PROTO_EXTENDS_FUNCTION_CONST()                                                \
389            BOOST_PROTO_EXTENDS_FUNCTION_()                                                         \
390            BOOST_PROTO_DEFINE_FUN_OP_VARIADIC_IMPL_(BOOST_PROTO_CONST)                             \
391            /**/
392
393        #define BOOST_PROTO_EXTENDS_FUNCTION_NON_CONST()                                            \
394            BOOST_PROTO_EXTENDS_FUNCTION_()                                                         \
395            BOOST_PROTO_DEFINE_FUN_OP_VARIADIC_IMPL_(BOOST_PP_EMPTY)                                \
396            /**/
397
398        #define BOOST_PROTO_EXTENDS_FUNCTION()                                                      \
399            BOOST_PROTO_EXTENDS_FUNCTION_()                                                         \
400            BOOST_PROTO_DEFINE_FUN_OP_VARIADIC_IMPL_(BOOST_PP_EMPTY)                                \
401            BOOST_PROTO_DEFINE_FUN_OP_VARIADIC_IMPL_(BOOST_PROTO_CONST)                             \
402            /**/
403    #else
404        #define BOOST_PROTO_EXTENDS_FUNCTION_CONST()                                                \
405            BOOST_PROTO_EXTENDS_FUNCTION_()                                                         \
406            BOOST_PP_REPEAT_FROM_TO(                                                                \
407                0                                                                                   \
408              , BOOST_PROTO_MAX_FUNCTION_CALL_ARITY                                                 \
409              , BOOST_PROTO_DEFINE_FUN_OP_CONST                                                     \
410              , ~                                                                                   \
411            )                                                                                       \
412            /**/
413
414        #define BOOST_PROTO_EXTENDS_FUNCTION_NON_CONST()                                            \
415            BOOST_PROTO_EXTENDS_FUNCTION_()                                                         \
416            BOOST_PP_REPEAT_FROM_TO(                                                                \
417                0                                                                                   \
418              , BOOST_PROTO_MAX_FUNCTION_CALL_ARITY                                                 \
419              , BOOST_PROTO_DEFINE_FUN_OP_NON_CONST                                                 \
420              , ~                                                                                   \
421            )                                                                                       \
422            /**/
423
424        #define BOOST_PROTO_EXTENDS_FUNCTION()                                                      \
425            BOOST_PROTO_EXTENDS_FUNCTION_()                                                         \
426            BOOST_PP_REPEAT_FROM_TO(                                                                \
427                0                                                                                   \
428              , BOOST_PROTO_MAX_FUNCTION_CALL_ARITY                                                 \
429              , BOOST_PROTO_DEFINE_FUN_OP                                                           \
430              , ~                                                                                   \
431            )                                                                                       \
432            /**/
433    #endif
434
435    #define BOOST_PROTO_EXTENDS(Expr, Derived, Domain)                                              \
436        BOOST_PROTO_BASIC_EXTENDS(Expr, Derived, Domain)                                            \
437        BOOST_PROTO_EXTENDS_ASSIGN()                                                                \
438        BOOST_PROTO_EXTENDS_SUBSCRIPT()                                                             \
439        BOOST_PROTO_EXTENDS_FUNCTION()                                                              \
440        /**/
441
442    #define BOOST_PROTO_EXTENDS_USING_ASSIGN(Derived)                                               \
443        typedef typename Derived::proto_extends proto_extends;                                      \
444        using proto_extends::operator =;                                                            \
445        BOOST_PROTO_EXTENDS_COPY_ASSIGN_(Derived, BOOST_PROTO_TYPENAME)                             \
446        /**/
447
448    #define BOOST_PROTO_EXTENDS_USING_ASSIGN_NON_DEPENDENT(Derived)                                 \
449        typedef Derived::proto_extends proto_extends;                                               \
450        using proto_extends::operator =;                                                            \
451        BOOST_PROTO_EXTENDS_COPY_ASSIGN_(Derived, BOOST_PP_EMPTY)                                   \
452        /**/
453
454    namespace exprns_
455    {
456        /// \brief Empty type to be used as a dummy template parameter of
457        ///     POD expression wrappers. It allows argument-dependent lookup
458        ///     to find Proto's operator overloads.
459        ///
460        /// \c proto::is_proto_expr allows argument-dependent lookup
461        ///     to find Proto's operator overloads. For example:
462        ///
463        /// \code
464        /// template<typename T, typename Dummy = proto::is_proto_expr>
465        /// struct my_terminal
466        /// {
467        ///     BOOST_PROTO_BASIC_EXTENDS(
468        ///         typename proto::terminal<T>::type
469        ///       , my_terminal<T>
470        ///       , default_domain
471        ///     )
472        /// };
473        ///
474        /// // ...
475        /// my_terminal<int> _1, _2;
476        /// _1 + _2; // OK, uses proto::operator+
477        /// \endcode
478        ///
479        /// Without the second \c Dummy template parameter, Proto's operator
480        /// overloads would not be considered by name lookup.
481        struct is_proto_expr
482        {};
483
484        /// \brief extends\<\> class template for adding behaviors to a Proto expression template
485        ///
486        template<
487            typename Expr
488          , typename Derived
489          , typename Domain     // = proto::default_domain
490          , long Arity          // = Expr::proto_arity_c
491        >
492        struct extends
493        {
494            extends()
495              : proto_expr_()
496            {}
497
498            extends(extends const &that)
499              : proto_expr_(that.proto_expr_)
500            {}
501
502            extends(Expr const &expr_)
503              : proto_expr_(expr_)
504            {}
505
506            typedef extends proto_extends;
507            BOOST_PROTO_BASIC_EXTENDS_(Expr, Derived, Domain)
508            typedef typename Domain::proto_generator proto_generator;
509            BOOST_PROTO_EXTENDS_ASSIGN_CONST_()
510            BOOST_PROTO_EXTENDS_SUBSCRIPT_CONST()
511
512            // Instead of using BOOST_PROTO_EXTENDS_FUNCTION, which uses
513            // nested preprocessor loops, use file iteration here to generate
514            // the operator() overloads, which is more efficient.
515            #include <boost/proto/detail/extends_funop_const.hpp>
516        };
517
518        /// \brief extends\<\> class template for adding behaviors to a Proto expression template
519        ///
520        template<typename Expr, typename Derived, typename Domain>
521        struct extends<Expr, Derived, Domain, 0>
522        {
523            extends()
524              : proto_expr_()
525            {}
526
527            extends(extends const &that)
528              : proto_expr_(that.proto_expr_)
529            {}
530
531            extends(Expr const &expr_)
532              : proto_expr_(expr_)
533            {}
534
535            typedef extends proto_extends;
536            BOOST_PROTO_BASIC_EXTENDS_(Expr, Derived, Domain)
537            typedef typename Domain::proto_generator proto_generator;
538            BOOST_PROTO_EXTENDS_ASSIGN_()
539            BOOST_PROTO_EXTENDS_SUBSCRIPT()
540
541            // Instead of using BOOST_PROTO_EXTENDS_FUNCTION, which uses
542            // nested preprocessor loops, use file iteration here to generate
543            // the operator() overloads, which is more efficient.
544            #include <boost/proto/detail/extends_funop.hpp>
545        };
546
547        /// INTERNAL ONLY
548        ///
549        template<typename This, typename Fun, typename Domain>
550        struct virtual_member
551        {
552            typedef Domain proto_domain;
553            typedef typename Domain::proto_generator proto_generator;
554            typedef virtual_member<This, Fun, Domain> proto_derived_expr;
555            typedef tag::member proto_tag;
556            typedef list2<This &, expr<tag::terminal, term<Fun> > const &> proto_args;
557            typedef mpl::long_<2> proto_arity;
558            typedef detail::not_a_valid_type proto_address_of_hack_type_;
559            typedef void proto_is_expr_; /**< INTERNAL ONLY */
560            static const long proto_arity_c = 2;
561            typedef boost::proto::tag::proto_expr fusion_tag;
562            typedef This &proto_child0;
563            typedef expr<tag::terminal, term<Fun> > const &proto_child1;
564            typedef expr<proto_tag, proto_args, proto_arity_c> proto_base_expr;
565            typedef basic_expr<proto_tag, proto_args, proto_arity_c> proto_grammar;
566            typedef void proto_is_aggregate_; /**< INTERNAL ONLY */
567
568            BOOST_PROTO_EXTENDS_ASSIGN_()
569            BOOST_PROTO_EXTENDS_SUBSCRIPT()
570
571            // Instead of using BOOST_PROTO_EXTENDS_FUNCTION, which uses
572            // nested preprocessor loops, use file iteration here to generate
573            // the operator() overloads, which is more efficient.
574            #define BOOST_PROTO_NO_WAVE_OUTPUT
575            #include <boost/proto/detail/extends_funop.hpp>
576            #undef BOOST_PROTO_NO_WAVE_OUTPUT
577
578            proto_base_expr const proto_base() const
579            {
580                proto_base_expr that = {this->child0(), this->child1()};
581                return that;
582            }
583
584            proto_child0 child0() const
585            {
586                using std::size_t;
587                return *(This *)((char *)this - BOOST_PROTO_OFFSETOF(This, proto_member_union_start_));
588            }
589
590            proto_child1 child1() const
591            {
592                static expr<tag::terminal, term<Fun>, 0> const that = {Fun()};
593                return that;
594            }
595        };
596
597        /// INTERNAL ONLY
598        ///
599        #define BOOST_PROTO_EXTENDS_MEMBER_(R, DOMAIN, ELEM)                                            \
600            boost::proto::exprns_::virtual_member<                                                      \
601                proto_derived_expr                                                                      \
602              , BOOST_PP_TUPLE_ELEM(2, 0, ELEM)                                                         \
603              , DOMAIN                                                                                  \
604            > BOOST_PP_TUPLE_ELEM(2, 1, ELEM);                                                          \
605            /**/
606
607        /// \brief For declaring virtual data members in an extension class.
608        ///
609        #define BOOST_PROTO_EXTENDS_MEMBERS_WITH_DOMAIN(SEQ, DOMAIN)                                    \
610            union                                                                                       \
611            {                                                                                           \
612                char proto_member_union_start_;                                                         \
613                BOOST_PP_SEQ_FOR_EACH(BOOST_PROTO_EXTENDS_MEMBER_, DOMAIN, SEQ)                         \
614            };                                                                                          \
615            /**/
616
617        /// \brief For declaring virtual data members in an extension class.
618        ///
619        #define BOOST_PROTO_EXTENDS_MEMBERS(SEQ)                                                        \
620            BOOST_PROTO_EXTENDS_MEMBERS_WITH_DOMAIN(SEQ, proto_domain)                                  \
621            /**/
622
623    }
624
625}}
626
627#endif