123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212 |
- // Copyright (c) 2001-2011 Hartmut Kaiser
- //
- // Distributed under the Boost Software License, Version 1.0. (See accompanying
- // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
- #if !defined(BOOST_SPIRIT_SUPPORT_META_CREATE_NOV_21_2009_0327PM)
- #define BOOST_SPIRIT_SUPPORT_META_CREATE_NOV_21_2009_0327PM
- #if defined(_MSC_VER)
- #pragma once
- #endif
- #include <boost/spirit/home/support/unused.hpp>
- #include <boost/version.hpp>
- #include <boost/proto/make_expr.hpp>
- #include <boost/proto/traits.hpp>
- #include <boost/utility/result_of.hpp>
- #include <boost/type_traits/add_const.hpp>
- #include <boost/type_traits/add_reference.hpp>
- #include <boost/type_traits/remove_const.hpp>
- #include <boost/type_traits/remove_reference.hpp>
- #include <boost/fusion/include/fold.hpp>
- #include <boost/mpl/and.hpp>
- #include <boost/mpl/not.hpp>
- // needed for workaround below
- #if defined(__GNUC__) && ((__GNUC__ < 4) || (__GNUC__ == 4) && (__GNUC_MINOR__ < 3))
- #include <boost/type_traits/is_same.hpp>
- #endif
- namespace boost { namespace spirit { namespace traits
- {
- ///////////////////////////////////////////////////////////////////////////
- // This is the main dispatch point for meta_create to the correct domain
- template <typename Domain, typename T, typename Enable = void>
- struct meta_create;
- ///////////////////////////////////////////////////////////////////////////
- // This allows to query whether a valid mapping exists for the given data
- // type to a component in the given domain
- template <typename Domain, typename T, typename Enable = void>
- struct meta_create_exists : mpl::false_ {};
- }}}
- namespace boost { namespace spirit
- {
- ///////////////////////////////////////////////////////////////////////////
- namespace detail
- {
- template <typename T>
- struct add_const_ref
- : add_reference<typename add_const<T>::type> {};
- template <typename T>
- struct remove_const_ref
- : remove_const<typename remove_reference<T>::type> {};
- // starting with Boost V1.42 fusion::fold has been changed to be compatible
- // with mpl::fold (the sequence of template parameters for the meta-function
- // object has been changed)
- #if BOOST_VERSION < 104200
- ///////////////////////////////////////////////////////////////////////
- template <typename OpTag, typename Domain>
- struct nary_proto_expr_function
- {
- template <typename T>
- struct result;
- // this is a workaround for older versions of g++ (< V4.3) which apparently have
- // problems with the following template specialization
- #if defined(__GNUC__) && ((__GNUC__ < 4) || (__GNUC__ == 4) && (__GNUC_MINOR__ < 3))
- template <typename F, typename T1, typename T2>
- struct result<F(T1, T2)>
- {
- BOOST_STATIC_ASSERT((is_same<F, nary_proto_expr_function>::value));
- #else
- template <typename T1, typename T2>
- struct result<nary_proto_expr_function(T1, T2)>
- {
- #endif
- typedef typename remove_const_ref<T2>::type left_type;
- typedef typename
- spirit::traits::meta_create<Domain, T1>::type
- right_type;
- typedef typename mpl::eval_if<
- traits::not_is_unused<left_type>
- , proto::result_of::make_expr<OpTag, left_type, right_type>
- , mpl::identity<right_type>
- >::type type;
- };
- template <typename T>
- typename result<nary_proto_expr_function(T, unused_type const&)>::type
- operator()(T, unused_type const&) const
- {
- typedef spirit::traits::meta_create<Domain, T> right_type;
- return right_type::call();
- }
- template <typename T1, typename T2>
- typename result<nary_proto_expr_function(T1, T2)>::type
- operator()(T1, T2 const& t2) const
- {
- // we variants to the alternative operator
- typedef spirit::traits::meta_create<Domain, T1> right_type;
- return proto::make_expr<OpTag>(t2, right_type::call());
- }
- };
- #else
- ///////////////////////////////////////////////////////////////////////
- template <typename OpTag, typename Domain>
- struct nary_proto_expr_function
- {
- template <typename T>
- struct result;
- // this is a workaround for older versions of g++ (< V4.3) which apparently have
- // problems with the following template specialization
- #if defined(__GNUC__) && ((__GNUC__ < 4) || (__GNUC__ == 4) && (__GNUC_MINOR__ < 3))
- template <typename F, typename T1, typename T2>
- struct result<F(T1, T2)>
- {
- BOOST_STATIC_ASSERT((is_same<F, nary_proto_expr_function>::value));
- #else
- template <typename T1, typename T2>
- struct result<nary_proto_expr_function(T1, T2)>
- {
- #endif
- typedef typename remove_const_ref<T1>::type left_type;
- typedef typename
- spirit::traits::meta_create<Domain, T2>::type
- right_type;
- typedef typename mpl::eval_if<
- traits::not_is_unused<left_type>
- , proto::result_of::make_expr<OpTag, left_type, right_type>
- , mpl::identity<right_type>
- >::type type;
- };
- template <typename T>
- typename result<nary_proto_expr_function(unused_type const&, T)>::type
- operator()(unused_type const&, T) const
- {
- typedef spirit::traits::meta_create<Domain, T> right_type;
- return right_type::call();
- }
- template <typename T1, typename T2>
- typename result<nary_proto_expr_function(T1, T2)>::type
- operator()(T1 const& t1, T2) const
- {
- // we variants to the alternative operator
- typedef spirit::traits::meta_create<Domain, T2> right_type;
- return proto::make_expr<OpTag>(t1, right_type::call());
- }
- };
- #endif
- }
- ///////////////////////////////////////////////////////////////////////
- template <typename T, typename OpTag, typename Domain>
- struct make_unary_proto_expr
- {
- typedef spirit::traits::meta_create<Domain, T> subject_type;
- typedef typename proto::result_of::make_expr<
- OpTag, typename subject_type::type
- >::type type;
- static type call()
- {
- return proto::make_expr<OpTag>(subject_type::call());
- }
- };
- ///////////////////////////////////////////////////////////////////////////
- template <typename Sequence, typename OpTag, typename Domain>
- struct make_nary_proto_expr
- {
- typedef detail::nary_proto_expr_function<OpTag, Domain>
- make_proto_expr;
- typedef typename fusion::result_of::fold<
- Sequence, unused_type, make_proto_expr
- >::type type;
- static type call()
- {
- return fusion::fold(Sequence(), unused, make_proto_expr());
- }
- };
- ///////////////////////////////////////////////////////////////////////////
- namespace detail
- {
- // Starting with newer versions of Proto, all Proto expressions are at
- // the same time Fusion sequences. This is the correct behavior, but
- // we need to distinguish between Fusion sequences and Proto
- // expressions. This meta-function does exactly that.
- template <typename T>
- struct is_fusion_sequence_but_not_proto_expr
- : mpl::and_<
- fusion::traits::is_sequence<T>
- , mpl::not_<proto::is_expr<T> > >
- {};
- }
- }}
- #endif
|