PageRenderTime 48ms CodeModel.GetById 13ms app.highlight 24ms RepoModel.GetById 8ms app.codeStats 0ms

/Src/Dependencies/Boost/boost/spirit/home/support/auto/meta_create.hpp

http://hadesmem.googlecode.com/
C++ Header | 212 lines | 157 code | 26 blank | 29 comment | 12 complexity | 3423fb29353e14d3fdc61047efd0674b MD5 | raw file
  1//  Copyright (c) 2001-2011 Hartmut Kaiser
  2//
  3//  Distributed under the Boost Software License, Version 1.0. (See accompanying
  4//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5
  6#if !defined(BOOST_SPIRIT_SUPPORT_META_CREATE_NOV_21_2009_0327PM)
  7#define BOOST_SPIRIT_SUPPORT_META_CREATE_NOV_21_2009_0327PM
  8
  9#if defined(_MSC_VER)
 10#pragma once
 11#endif
 12
 13#include <boost/spirit/home/support/unused.hpp>
 14
 15#include <boost/version.hpp>
 16#include <boost/spirit/include/phoenix_limits.hpp>      // needs to be included before proto
 17#include <boost/proto/proto.hpp>
 18#include <boost/utility/result_of.hpp>
 19#include <boost/type_traits/add_const.hpp>
 20#include <boost/type_traits/add_reference.hpp>
 21#include <boost/type_traits/remove_const.hpp>
 22#include <boost/type_traits/remove_reference.hpp>
 23#include <boost/fusion/include/fold.hpp>
 24#include <boost/mpl/and.hpp>
 25#include <boost/mpl/not.hpp>
 26
 27// needed for workaround below
 28#if defined(__GNUC__) && ((__GNUC__ < 4) || (__GNUC__ == 4) && (__GNUC_MINOR__ < 3))
 29#include <boost/type_traits/is_same.hpp>
 30#endif
 31
 32namespace boost { namespace spirit { namespace traits
 33{
 34    ///////////////////////////////////////////////////////////////////////////
 35    // This is the main dispatch point for meta_create to the correct domain
 36    template <typename Domain, typename T, typename Enable = void>
 37    struct meta_create;
 38
 39    ///////////////////////////////////////////////////////////////////////////
 40    // This allows to query whether a valid mapping exists for the given data 
 41    // type to a component in the given domain
 42    template <typename Domain, typename T, typename Enable = void>
 43    struct meta_create_exists : mpl::false_ {};
 44}}}
 45
 46namespace boost { namespace spirit 
 47{
 48    ///////////////////////////////////////////////////////////////////////////
 49    namespace detail
 50    {
 51        template <typename T>
 52        struct add_const_ref
 53          : add_reference<typename add_const<T>::type> {};
 54
 55        template <typename T>
 56        struct remove_const_ref
 57          : remove_const<typename remove_reference<T>::type> {};
 58
 59// starting with Boost V1.42 fusion::fold has been changed to be compatible 
 60// with mpl::fold (the sequence of template parameters for the meta-function 
 61// object has been changed)
 62#if BOOST_VERSION < 104200
 63        ///////////////////////////////////////////////////////////////////////
 64        template <typename OpTag, typename Domain>
 65        struct nary_proto_expr_function
 66        {
 67            template <typename T>
 68            struct result;
 69
 70// this is a workaround for older versions of g++ (< V4.3) which apparently have
 71// problems with the following template specialization
 72#if defined(__GNUC__) && ((__GNUC__ < 4) || (__GNUC__ == 4) && (__GNUC_MINOR__ < 3))
 73            template <typename F, typename T1, typename T2>
 74            struct result<F(T1, T2)>
 75            {
 76                BOOST_STATIC_ASSERT((is_same<F, nary_proto_expr_function>::value));
 77#else
 78            template <typename T1, typename T2>
 79            struct result<nary_proto_expr_function(T1, T2)>
 80            {
 81#endif
 82                typedef typename remove_const_ref<T2>::type left_type;
 83                typedef typename 
 84                    spirit::traits::meta_create<Domain, T1>::type
 85                right_type;
 86
 87                typedef typename mpl::eval_if<
 88                    traits::not_is_unused<left_type>
 89                  , proto::result_of::make_expr<OpTag, left_type, right_type>
 90                  , mpl::identity<right_type>
 91                >::type type;
 92            };
 93
 94            template <typename T>
 95            typename result<nary_proto_expr_function(T, unused_type const&)>::type
 96            operator()(T, unused_type const&) const
 97            {
 98                typedef spirit::traits::meta_create<Domain, T> right_type;
 99                return right_type::call();
100            }
101
102            template <typename T1, typename T2>
103            typename result<nary_proto_expr_function(T1, T2)>::type
104            operator()(T1, T2 const& t2) const
105            {
106                // we variants to the alternative operator
107                typedef spirit::traits::meta_create<Domain, T1> right_type;
108                return proto::make_expr<OpTag>(t2, right_type::call());
109            }
110        };
111#else
112        ///////////////////////////////////////////////////////////////////////
113        template <typename OpTag, typename Domain>
114        struct nary_proto_expr_function
115        {
116            template <typename T>
117            struct result;
118
119// this is a workaround for older versions of g++ (< V4.3) which apparently have
120// problems with the following template specialization
121#if defined(__GNUC__) && ((__GNUC__ < 4) || (__GNUC__ == 4) && (__GNUC_MINOR__ < 3))
122            template <typename F, typename T1, typename T2>
123            struct result<F(T1, T2)>
124            {
125                BOOST_STATIC_ASSERT((is_same<F, nary_proto_expr_function>::value));
126#else
127            template <typename T1, typename T2>
128            struct result<nary_proto_expr_function(T1, T2)>
129            {
130#endif
131                typedef typename remove_const_ref<T1>::type left_type;
132                typedef typename 
133                    spirit::traits::meta_create<Domain, T2>::type
134                right_type;
135
136                typedef typename mpl::eval_if<
137                    traits::not_is_unused<left_type>
138                  , proto::result_of::make_expr<OpTag, left_type, right_type>
139                  , mpl::identity<right_type>
140                >::type type;
141            };
142
143            template <typename T>
144            typename result<nary_proto_expr_function(unused_type const&, T)>::type
145            operator()(unused_type const&, T) const
146            {
147                typedef spirit::traits::meta_create<Domain, T> right_type;
148                return right_type::call();
149            }
150
151            template <typename T1, typename T2>
152            typename result<nary_proto_expr_function(T1, T2)>::type
153            operator()(T1 const& t1, T2) const
154            {
155                // we variants to the alternative operator
156                typedef spirit::traits::meta_create<Domain, T2> right_type;
157                return proto::make_expr<OpTag>(t1, right_type::call());
158            }
159        };
160#endif
161    }
162
163    ///////////////////////////////////////////////////////////////////////
164    template <typename T, typename OpTag, typename Domain>
165    struct make_unary_proto_expr
166    {
167        typedef spirit::traits::meta_create<Domain, T> subject_type;
168
169        typedef typename proto::result_of::make_expr<
170            OpTag, typename subject_type::type
171        >::type type;
172
173        static type call()
174        {
175            return proto::make_expr<OpTag>(subject_type::call());
176        }
177    };
178
179    ///////////////////////////////////////////////////////////////////////////
180    template <typename Sequence, typename OpTag, typename Domain>
181    struct make_nary_proto_expr
182    {
183        typedef detail::nary_proto_expr_function<OpTag, Domain> 
184            make_proto_expr;
185
186        typedef typename fusion::result_of::fold<
187            Sequence, unused_type, make_proto_expr
188        >::type type;
189
190        static type call()
191        {
192            return fusion::fold(Sequence(), unused, make_proto_expr());
193        }
194    };
195
196    ///////////////////////////////////////////////////////////////////////////
197    namespace detail
198    {
199        // Starting with newer versions of Proto, all Proto expressions are at 
200        // the same time Fusion sequences. This is the correct behavior, but
201        // we need to distinguish between Fusion sequences and Proto 
202        // expressions. This meta-function does exactly that.
203        template <typename T>
204        struct is_fusion_sequence_but_not_proto_expr
205          : mpl::and_<
206                fusion::traits::is_sequence<T>
207              , mpl::not_<proto::is_expr<T> > >
208        {};
209    }
210}}
211
212#endif