PageRenderTime 74ms CodeModel.GetById 21ms app.highlight 48ms RepoModel.GetById 1ms app.codeStats 1ms

/Src/Dependencies/Boost/boost/proto/detail/decltype.hpp

http://hadesmem.googlecode.com/
C++ Header | 501 lines | 388 code | 68 blank | 45 comment | 4 complexity | c71d1a46cb6b99bbdcbb15c9a92777c0 MD5 | raw file
  1///////////////////////////////////////////////////////////////////////////////
  2/// \file decltype.hpp
  3/// Contains definition the BOOST_PROTO_DECLTYPE_() macro and assorted helpers
  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_DETAIL_DECLTYPE_HPP_EAN_04_04_2008
 10#define BOOST_PROTO_DETAIL_DECLTYPE_HPP_EAN_04_04_2008
 11
 12#include <boost/config.hpp>
 13#include <boost/detail/workaround.hpp>
 14#include <boost/get_pointer.hpp>
 15#include <boost/preprocessor/cat.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/repeat.hpp>
 20#include <boost/preprocessor/repetition/repeat_from_to.hpp>
 21#include <boost/preprocessor/iteration/local.hpp>
 22#include <boost/mpl/if.hpp>
 23#include <boost/mpl/eval_if.hpp>
 24#include <boost/mpl/identity.hpp>
 25#include <boost/type_traits/is_class.hpp>
 26#include <boost/type_traits/remove_reference.hpp>
 27#include <boost/type_traits/is_pointer.hpp>
 28#include <boost/type_traits/is_function.hpp>
 29#include <boost/type_traits/is_member_object_pointer.hpp>
 30#include <boost/type_traits/add_const.hpp>
 31#include <boost/type_traits/add_reference.hpp>
 32#include <boost/typeof/typeof.hpp>
 33#include <boost/utility/addressof.hpp>
 34#include <boost/utility/result_of.hpp>
 35#include <boost/utility/enable_if.hpp>
 36
 37#ifndef BOOST_NO_DECLTYPE
 38# define BOOST_PROTO_DECLTYPE_(EXPR, TYPE) typedef decltype(EXPR) TYPE;
 39#else
 40# define BOOST_PROTO_DECLTYPE_NESTED_TYPEDEF_TPL_(NESTED, EXPR)                                     \
 41    BOOST_TYPEOF_NESTED_TYPEDEF_TPL(BOOST_PP_CAT(nested_and_hidden_, NESTED), EXPR)                 \
 42    static int const sz = sizeof(boost::proto::detail::check_reference(EXPR));                      \
 43    struct NESTED                                                                                   \
 44      : boost::mpl::if_c<                                                                           \
 45            1==sz                                                                                   \
 46          , typename BOOST_PP_CAT(nested_and_hidden_, NESTED)::type &                               \
 47          , typename BOOST_PP_CAT(nested_and_hidden_, NESTED)::type                                 \
 48        >                                                                                           \
 49    {};
 50# define BOOST_PROTO_DECLTYPE_(EXPR, TYPE)                                                          \
 51    BOOST_PROTO_DECLTYPE_NESTED_TYPEDEF_TPL_(BOOST_PP_CAT(nested_, TYPE), (EXPR))                   \
 52    typedef typename BOOST_PP_CAT(nested_, TYPE)::type TYPE;
 53#endif
 54
 55namespace boost { namespace proto
 56{
 57    namespace detail
 58    {
 59        namespace anyns
 60        {
 61            ////////////////////////////////////////////////////////////////////////////////////////////
 62            struct any
 63            {
 64                any(...);
 65                any operator=(any);
 66                any operator[](any);
 67                #define M0(Z, N, DATA) any operator()(BOOST_PP_ENUM_PARAMS_Z(Z, N, any BOOST_PP_INTERCEPT));
 68                BOOST_PP_REPEAT(BOOST_PROTO_MAX_ARITY, M0, ~)
 69                #undef M0
 70
 71                template<typename T>
 72                operator T &() const volatile;
 73
 74                any operator+();
 75                any operator-();
 76                any operator*();
 77                any operator&();
 78                any operator~();
 79                any operator!();
 80                any operator++();
 81                any operator--();
 82                any operator++(int);
 83                any operator--(int);
 84
 85                friend any operator<<(any, any);
 86                friend any operator>>(any, any);
 87                friend any operator*(any, any);
 88                friend any operator/(any, any);
 89                friend any operator%(any, any);
 90                friend any operator+(any, any);
 91                friend any operator-(any, any);
 92                friend any operator<(any, any);
 93                friend any operator>(any, any);
 94                friend any operator<=(any, any);
 95                friend any operator>=(any, any);
 96                friend any operator==(any, any);
 97                friend any operator!=(any, any);
 98                friend any operator||(any, any);
 99                friend any operator&&(any, any);
100                friend any operator&(any, any);
101                friend any operator|(any, any);
102                friend any operator^(any, any);
103                friend any operator,(any, any);
104                friend any operator->*(any, any);
105
106                friend any operator<<=(any, any);
107                friend any operator>>=(any, any);
108                friend any operator*=(any, any);
109                friend any operator/=(any, any);
110                friend any operator%=(any, any);
111                friend any operator+=(any, any);
112                friend any operator-=(any, any);
113                friend any operator&=(any, any);
114                friend any operator|=(any, any);
115                friend any operator^=(any, any);
116            };
117        }
118
119        using anyns::any;
120
121        ////////////////////////////////////////////////////////////////////////////////////////////
122        template<typename T>
123        struct as_mutable
124        {
125            typedef T &type;
126        };
127
128        template<typename T>
129        struct as_mutable<T &>
130        {
131            typedef T &type;
132        };
133
134        template<typename T>
135        struct as_mutable<T const &>
136        {
137            typedef T &type;
138        };
139
140        ////////////////////////////////////////////////////////////////////////////////////////////
141        template<typename T>
142        T make();
143
144        ////////////////////////////////////////////////////////////////////////////////////////////
145        template<typename T>
146        typename as_mutable<T>::type make_mutable();
147
148        ////////////////////////////////////////////////////////////////////////////////////////////
149        template<typename T>
150        struct subscript_wrapper
151          : T
152        {
153            using T::operator[];
154
155            #if BOOST_WORKAROUND(BOOST_MSVC, BOOST_TESTED_AT(1500))
156            any operator[](any const volatile &) const volatile;
157            #else
158            any operator[](any const &) const volatile;
159            #endif
160        };
161
162        ////////////////////////////////////////////////////////////////////////////////////////////
163        template<typename T>
164        struct as_subscriptable
165        {
166            typedef
167                typename mpl::if_c<
168                    is_class<T>::value
169                  , subscript_wrapper<T>
170                  , T
171                >::type
172            type;
173        };
174
175        template<typename T>
176        struct as_subscriptable<T const>
177        {
178            typedef
179                typename mpl::if_c<
180                    is_class<T>::value
181                  , subscript_wrapper<T> const
182                  , T const
183                >::type
184            type;
185        };
186
187        template<typename T>
188        struct as_subscriptable<T &>
189        {
190            typedef
191                typename mpl::if_c<
192                    is_class<T>::value
193                  , subscript_wrapper<T> &
194                  , T &
195                >::type
196            type;
197        };
198
199        template<typename T>
200        struct as_subscriptable<T const &>
201        {
202            typedef
203                typename mpl::if_c<
204                    is_class<T>::value
205                  , subscript_wrapper<T> const &
206                  , T const &
207                >::type
208            type;
209        };
210
211        ////////////////////////////////////////////////////////////////////////////////////////////
212        template<typename T>
213        typename as_subscriptable<T>::type make_subscriptable();
214
215        ////////////////////////////////////////////////////////////////////////////////////////////
216        template<typename T>
217        char check_reference(T &);
218
219        template<typename T>
220        char (&check_reference(T const &))[2];
221
222        namespace has_get_pointerns
223        {
224            using boost::get_pointer;
225            void *(&get_pointer(...))[2];
226
227            ////////////////////////////////////////////////////////////////////////////////////////////
228            template<typename T>
229            struct has_get_pointer
230            {
231                static const bool value = sizeof(void *) == sizeof(get_pointer(make<T &>()));
232                typedef mpl::bool_<value> type;
233            };
234        }
235
236        using has_get_pointerns::has_get_pointer;
237
238        ////////////////////////////////////////////////////////////////////////////////////////////
239        template<typename T>
240        struct classtypeof;
241
242        template<typename T, typename U>
243        struct classtypeof<T U::*>
244        {
245            typedef U type;
246        };
247
248        // Other specializations are generated by the preprocessor
249        #include <boost/proto/detail/classtypeof.hpp>
250
251        ////////////////////////////////////////////////////////////////////////////////////////////
252        template<typename T>
253        T &lvalue(T &t)
254        {
255            return t;
256        }
257
258        template<typename T>
259        T const &lvalue(T const &t)
260        {
261            return t;
262        }
263
264        ////////////////////////////////////////////////////////////////////////////////////////////
265        template<typename U, typename V, typename T>
266        U *proto_get_pointer(T &t, V *, U *)
267        {
268            return boost::addressof(t);
269        }
270
271        template<typename U, typename V, typename T>
272        U const *proto_get_pointer(T &t, V *, U const *)
273        {
274            return boost::addressof(t);
275        }
276
277        template<typename U, typename V, typename T>
278        V *proto_get_pointer(T &t, V *, ...)
279        {
280            return get_pointer(t);
281        }
282
283        ////////////////////////////////////////////////////////////////////////////////////////////
284        #define BOOST_PROTO_USE_GET_POINTER()                                                       \
285        using namespace boost::proto::detail::get_pointerns                                         \
286        /**/
287
288        #define BOOST_PROTO_GET_POINTER(Type, Obj)                                                  \
289        boost::proto::detail::proto_get_pointer<Type>(                                              \
290            boost::proto::detail::lvalue(Obj)                                                       \
291          , (true ? 0 : get_pointer(Obj))                                                           \
292          , (true ? 0 : boost::addressof(boost::proto::detail::lvalue(Obj)))                        \
293        )                                                                                           \
294        /**/
295
296        ////////////////////////////////////////////////////////////////////////////////////////////
297        namespace get_pointerns
298        {
299            using boost::get_pointer;
300
301            template<typename T>
302            typename disable_if_c<has_get_pointer<T>::value, T *>::type
303            get_pointer(T &t)
304            {
305                return boost::addressof(t);
306            }
307
308            template<typename T>
309            typename disable_if_c<has_get_pointer<T>::value, T const *>::type
310            get_pointer(T const &t)
311            {
312                return boost::addressof(t);
313            }
314
315            char test_ptr_to_const(void *);
316            char (&test_ptr_to_const(void const *))[2];
317
318            template<typename U> char test_V_is_a_U(U *);
319            template<typename U> char test_V_is_a_U(U const *);
320            template<typename U> char (&test_V_is_a_U(...))[2];
321
322            ////////////////////////////////////////////////////////////////////////////////////////////
323            // result_of_ is a wrapper around boost::result_of that also handles "invocations" of
324            // member object pointers.
325            template<typename T, typename Void = void>
326            struct result_of_
327              : BOOST_PROTO_RESULT_OF<T>
328            {};
329
330            template<typename T, typename U, typename V>
331            struct result_of_<T U::*(V), typename enable_if_c<is_member_object_pointer<T U::*>::value>::type>
332            {
333                static const bool is_V_a_smart_ptr = 2 == sizeof(test_V_is_a_U<U>(&lvalue(make<V>())));
334                static const bool is_ptr_to_const = 2 == sizeof(test_ptr_to_const(BOOST_PROTO_GET_POINTER(U, make<V>())));
335
336                // If V is not a U, then it is a (smart) pointer and we can always return an lvalue.
337                // Otherwise, we can only return an lvalue if we are given one.
338                typedef
339                    typename mpl::eval_if_c<
340                        (is_V_a_smart_ptr || is_reference<V>::value)
341                      , mpl::eval_if_c<
342                            is_ptr_to_const
343                          , add_reference<typename add_const<T>::type>
344                          , add_reference<T>
345                        >
346                      , mpl::identity<T>
347                    >::type
348                type;
349            };
350
351            ////////////////////////////////////////////////////////////////////////////////////////////
352            template<
353                typename T
354              , typename U
355              , bool IsMemPtr = is_member_object_pointer<
356                    typename remove_reference<U>::type
357                >::value
358            >
359            struct mem_ptr_fun
360            {
361                BOOST_PROTO_DECLTYPE_(
362                    proto::detail::make_mutable<T>() ->* proto::detail::make<U>()
363                  , result_type
364                )
365
366                result_type operator()(
367                    typename add_reference<typename add_const<T>::type>::type t
368                  , typename add_reference<typename add_const<U>::type>::type u
369                ) const
370                {
371                    return t ->* u;
372                }
373            };
374
375            ////////////////////////////////////////////////////////////////////////////////////////////
376            template<typename T, typename U>
377            struct mem_ptr_fun<T, U, true>
378            {
379                typedef
380                    typename classtypeof<
381                        typename uncvref<U>::type
382                    >::type
383                V;
384
385                BOOST_PROTO_DECLTYPE_(
386                    BOOST_PROTO_GET_POINTER(V, proto::detail::make_mutable<T>()) ->* proto::detail::make<U>()
387                  , result_type
388                )
389
390                result_type operator()(
391                    typename add_reference<typename add_const<T>::type>::type t
392                  , U u
393                ) const
394                {
395                    return BOOST_PROTO_GET_POINTER(V, t) ->* u;
396                }
397            };
398        }
399
400        using get_pointerns::result_of_;
401        using get_pointerns::mem_ptr_fun;
402
403        ////////////////////////////////////////////////////////////////////////////////////////////
404        template<typename A0, typename A1>
405        struct comma_result
406        {
407            BOOST_PROTO_DECLTYPE_((proto::detail::make<A0>(), proto::detail::make<A1>()), type)
408        };
409
410        template<typename A0>
411        struct comma_result<A0, void>
412        {
413            typedef void type;
414        };
415
416        template<typename A1>
417        struct comma_result<void, A1>
418        {
419            typedef A1 type;
420        };
421
422        template<>
423        struct comma_result<void, void>
424        {
425            typedef void type;
426        };
427
428        ////////////////////////////////////////////////////////////////////////////////////////////
429        // normalize a function type for use with boost::result_of
430        template<typename T, typename U = T>
431        struct result_of_fixup
432          : mpl::if_c<is_function<T>::value, T *, U>
433        {};
434
435        template<typename T, typename U>
436        struct result_of_fixup<T &, U>
437          : result_of_fixup<T, T>
438        {};
439
440        template<typename T, typename U>
441        struct result_of_fixup<T const &, U>
442          : result_of_fixup<T, T>
443        {};
444
445        template<typename T, typename U>
446        struct result_of_fixup<T *, U>
447          : result_of_fixup<T, U>
448        {};
449
450        template<typename R, typename T, typename U>
451        struct result_of_fixup<R T::*, U>
452        {
453            typedef R T::*type;
454        };
455
456        template<typename T, typename U>
457        struct result_of_fixup<T const, U>
458          : result_of_fixup<T, U>
459        {};
460
461        //// Tests for result_of_fixup
462        //struct bar {};
463        //BOOST_MPL_ASSERT((is_same<bar,        result_of_fixup<bar>::type>));
464        //BOOST_MPL_ASSERT((is_same<bar const,  result_of_fixup<bar const>::type>));
465        //BOOST_MPL_ASSERT((is_same<bar,        result_of_fixup<bar &>::type>));
466        //BOOST_MPL_ASSERT((is_same<bar const,  result_of_fixup<bar const &>::type>));
467        //BOOST_MPL_ASSERT((is_same<void(*)(),  result_of_fixup<void(*)()>::type>));
468        //BOOST_MPL_ASSERT((is_same<void(*)(),  result_of_fixup<void(* const)()>::type>));
469        //BOOST_MPL_ASSERT((is_same<void(*)(),  result_of_fixup<void(* const &)()>::type>));
470        //BOOST_MPL_ASSERT((is_same<void(*)(),  result_of_fixup<void(&)()>::type>));
471
472        template<typename T, typename PMF>
473        struct memfun
474        {
475            typedef typename uncvref<PMF>::type pmf_type;
476            typedef typename classtypeof<pmf_type>::type V;
477            typedef typename BOOST_PROTO_RESULT_OF<pmf_type(T)>::type result_type;
478
479            memfun(T t, PMF p)
480              : obj(t)
481              , pmf(p)
482            {}
483
484            result_type operator()() const
485            {
486                BOOST_PROTO_USE_GET_POINTER();
487                return (BOOST_PROTO_GET_POINTER(V, obj) ->* pmf)();
488            }
489
490            // Other overloads generated by the preprocessor
491            #include <boost/proto/detail/memfun_funop.hpp>
492
493        private:
494            T obj;
495            PMF pmf;
496        };
497
498    } // namespace detail
499}}
500
501#endif