Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-19 09:47:48

0001 //  Copyright (c) 2001-2011 Hartmut Kaiser
0002 //
0003 //  Distributed under the Boost Software License, Version 1.0. (See accompanying
0004 //  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0005 
0006 #if !defined(BOOST_SPIRIT_SUPPORT_META_CREATE_NOV_21_2009_0327PM)
0007 #define BOOST_SPIRIT_SUPPORT_META_CREATE_NOV_21_2009_0327PM
0008 
0009 #if defined(_MSC_VER)
0010 #pragma once
0011 #endif
0012 
0013 #include <boost/spirit/home/support/unused.hpp>
0014 
0015 #include <boost/version.hpp>
0016 #include <boost/proto/make_expr.hpp>
0017 #include <boost/proto/traits.hpp>
0018 #include <boost/utility/result_of.hpp>
0019 #include <boost/type_traits/add_const.hpp>
0020 #include <boost/type_traits/add_reference.hpp>
0021 #include <boost/type_traits/remove_const.hpp>
0022 #include <boost/type_traits/remove_reference.hpp>
0023 #include <boost/fusion/include/fold.hpp>
0024 #include <boost/mpl/and.hpp>
0025 #include <boost/mpl/not.hpp>
0026 
0027 // needed for workaround below
0028 #if defined(__GNUC__) && ((__GNUC__ < 4) || (__GNUC__ == 4) && (__GNUC_MINOR__ < 3))
0029 #include <boost/type_traits/is_same.hpp>
0030 #endif
0031 
0032 namespace boost { namespace spirit { namespace traits
0033 {
0034     ///////////////////////////////////////////////////////////////////////////
0035     // This is the main dispatch point for meta_create to the correct domain
0036     template <typename Domain, typename T, typename Enable = void>
0037     struct meta_create;
0038 
0039     ///////////////////////////////////////////////////////////////////////////
0040     // This allows to query whether a valid mapping exists for the given data 
0041     // type to a component in the given domain
0042     template <typename Domain, typename T, typename Enable = void>
0043     struct meta_create_exists : mpl::false_ {};
0044 }}}
0045 
0046 namespace boost { namespace spirit 
0047 {
0048     ///////////////////////////////////////////////////////////////////////////
0049     namespace detail
0050     {
0051         template <typename T>
0052         struct add_const_ref
0053           : add_reference<typename add_const<T>::type> {};
0054 
0055         template <typename T>
0056         struct remove_const_ref
0057           : remove_const<typename remove_reference<T>::type> {};
0058 
0059 // starting with Boost V1.42 fusion::fold has been changed to be compatible 
0060 // with mpl::fold (the sequence of template parameters for the meta-function 
0061 // object has been changed)
0062 #if BOOST_VERSION < 104200
0063         ///////////////////////////////////////////////////////////////////////
0064         template <typename OpTag, typename Domain>
0065         struct nary_proto_expr_function
0066         {
0067             template <typename T>
0068             struct result;
0069 
0070 // this is a workaround for older versions of g++ (< V4.3) which apparently have
0071 // problems with the following template specialization
0072 #if defined(__GNUC__) && ((__GNUC__ < 4) || (__GNUC__ == 4) && (__GNUC_MINOR__ < 3))
0073             template <typename F, typename T1, typename T2>
0074             struct result<F(T1, T2)>
0075             {
0076                 BOOST_STATIC_ASSERT((is_same<F, nary_proto_expr_function>::value));
0077 #else
0078             template <typename T1, typename T2>
0079             struct result<nary_proto_expr_function(T1, T2)>
0080             {
0081 #endif
0082                 typedef typename remove_const_ref<T2>::type left_type;
0083                 typedef typename 
0084                     spirit::traits::meta_create<Domain, T1>::type
0085                 right_type;
0086 
0087                 typedef typename mpl::eval_if<
0088                     traits::not_is_unused<left_type>
0089                   , proto::result_of::make_expr<OpTag, left_type, right_type>
0090                   , mpl::identity<right_type>
0091                 >::type type;
0092             };
0093 
0094             template <typename T>
0095             typename result<nary_proto_expr_function(T, unused_type const&)>::type
0096             operator()(T, unused_type const&) const
0097             {
0098                 typedef spirit::traits::meta_create<Domain, T> right_type;
0099                 return right_type::call();
0100             }
0101 
0102             template <typename T1, typename T2>
0103             typename result<nary_proto_expr_function(T1, T2)>::type
0104             operator()(T1, T2 const& t2) const
0105             {
0106                 // we variants to the alternative operator
0107                 typedef spirit::traits::meta_create<Domain, T1> right_type;
0108                 return proto::make_expr<OpTag>(t2, right_type::call());
0109             }
0110         };
0111 #else
0112         ///////////////////////////////////////////////////////////////////////
0113         template <typename OpTag, typename Domain>
0114         struct nary_proto_expr_function
0115         {
0116             template <typename T>
0117             struct result;
0118 
0119 // this is a workaround for older versions of g++ (< V4.3) which apparently have
0120 // problems with the following template specialization
0121 #if defined(__GNUC__) && ((__GNUC__ < 4) || (__GNUC__ == 4) && (__GNUC_MINOR__ < 3))
0122             template <typename F, typename T1, typename T2>
0123             struct result<F(T1, T2)>
0124             {
0125                 BOOST_STATIC_ASSERT((is_same<F, nary_proto_expr_function>::value));
0126 #else
0127             template <typename T1, typename T2>
0128             struct result<nary_proto_expr_function(T1, T2)>
0129             {
0130 #endif
0131                 typedef typename remove_const_ref<T1>::type left_type;
0132                 typedef typename 
0133                     spirit::traits::meta_create<Domain, T2>::type
0134                 right_type;
0135 
0136                 typedef typename mpl::eval_if<
0137                     traits::not_is_unused<left_type>
0138                   , proto::result_of::make_expr<OpTag, left_type, right_type>
0139                   , mpl::identity<right_type>
0140                 >::type type;
0141             };
0142 
0143             template <typename T>
0144             typename result<nary_proto_expr_function(unused_type const&, T)>::type
0145             operator()(unused_type const&, T) const
0146             {
0147                 typedef spirit::traits::meta_create<Domain, T> right_type;
0148                 return right_type::call();
0149             }
0150 
0151             template <typename T1, typename T2>
0152             typename result<nary_proto_expr_function(T1, T2)>::type
0153             operator()(T1 const& t1, T2) const
0154             {
0155                 // we variants to the alternative operator
0156                 typedef spirit::traits::meta_create<Domain, T2> right_type;
0157                 return proto::make_expr<OpTag>(t1, right_type::call());
0158             }
0159         };
0160 #endif
0161     }
0162 
0163     ///////////////////////////////////////////////////////////////////////
0164     template <typename T, typename OpTag, typename Domain>
0165     struct make_unary_proto_expr
0166     {
0167         typedef spirit::traits::meta_create<Domain, T> subject_type;
0168 
0169         typedef typename proto::result_of::make_expr<
0170             OpTag, typename subject_type::type
0171         >::type type;
0172 
0173         static type call()
0174         {
0175             return proto::make_expr<OpTag>(subject_type::call());
0176         }
0177     };
0178 
0179     ///////////////////////////////////////////////////////////////////////////
0180     template <typename Sequence, typename OpTag, typename Domain>
0181     struct make_nary_proto_expr
0182     {
0183         typedef detail::nary_proto_expr_function<OpTag, Domain> 
0184             make_proto_expr;
0185 
0186         typedef typename fusion::result_of::fold<
0187             Sequence, unused_type, make_proto_expr
0188         >::type type;
0189 
0190         static type call()
0191         {
0192             return fusion::fold(Sequence(), unused, make_proto_expr());
0193         }
0194     };
0195 
0196     ///////////////////////////////////////////////////////////////////////////
0197     namespace detail
0198     {
0199         // Starting with newer versions of Proto, all Proto expressions are at 
0200         // the same time Fusion sequences. This is the correct behavior, but
0201         // we need to distinguish between Fusion sequences and Proto 
0202         // expressions. This meta-function does exactly that.
0203         template <typename T>
0204         struct is_fusion_sequence_but_not_proto_expr
0205           : mpl::and_<
0206                 fusion::traits::is_sequence<T>
0207               , mpl::not_<proto::is_expr<T> > >
0208         {};
0209     }
0210 }}
0211 
0212 #endif