123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222 |
- /*=============================================================================
- Copyright (c) 2001-2011 Joel de Guzman
- Copyright (c) 2001-2011 Hartmut Kaiser
- http://spirit.sourceforge.net/
- 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_ACTION_DISPATCH_APRIL_18_2008_0720AM)
- #define BOOST_SPIRIT_ACTION_DISPATCH_APRIL_18_2008_0720AM
- #if defined(_MSC_VER)
- #pragma once
- #endif
- #include<boost/config.hpp>
- #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_LAMBDAS) && \
- !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_DECLTYPE)
- #include <utility>
- #include <type_traits>
- #endif
- #include <boost/spirit/home/support/attributes.hpp>
- namespace boost { namespace phoenix
- {
- template <typename Expr>
- struct actor;
- }}
- namespace boost { namespace spirit { namespace traits
- {
- template <typename Component>
- struct action_dispatch
- {
- #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_LAMBDAS) && \
- !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_DECLTYPE)
- // omit function parameters without specializing for each possible
- // type of callable entity
- // many thanks to Eelis/##iso-c++ for this contribution
- private:
- // this will be used to pass around POD types which are safe
- // to go through the ellipsis operator (if ever used)
- template <typename>
- struct fwd_tag {};
- // the first parameter is a placeholder to obtain SFINAE when
- // doing overload resolution, the second one is the actual
- // forwarder, where we can apply our implementation
- template <typename, typename T>
- struct fwd_storage { typedef T type; };
- // gcc should accept fake<T>() but it prints a sorry, needs
- // a check once the bug is sorted out, use a FAKE_CALL macro for now
- template <typename T>
- T fake_call();
- #define BOOST_SPIRIT_FAKE_CALL(T) (*(T*)0)
- // the forwarders, here we could tweak the implementation of
- // how parameters are passed to the functions, if needed
- struct fwd_none
- {
- template<typename F, typename... Rest>
- auto operator()(F && f, Rest&&...) -> decltype(f())
- {
- return f();
- }
- };
- struct fwd_attrib
- {
- template<typename F, typename A, typename... Rest>
- auto operator()(F && f, A && a, Rest&&...) -> decltype(f(a))
- {
- return f(a);
- }
- };
- struct fwd_attrib_context
- {
- template<typename F, typename A, typename B, typename... Rest>
- auto operator()(F && f, A && a, B && b, Rest&&...)
- -> decltype(f(a, b))
- {
- return f(a, b);
- }
- };
- struct fwd_attrib_context_pass
- {
- template<typename F, typename A, typename B, typename C
- , typename... Rest>
- auto operator()(F && f, A && a, B && b, C && c, Rest&&...)
- -> decltype(f(a, b, c))
- {
- return f(a, b, c);
- }
- };
- // SFINAE for our calling syntax, the forwarders are stored based
- // on what function call gives a proper result
- // this code can probably be more generic once implementations are
- // steady
- template <typename F>
- static auto do_call(F && f, ...)
- -> typename fwd_storage<decltype(f()), fwd_none>::type
- {
- return {};
- }
- template <typename F, typename A>
- static auto do_call(F && f, fwd_tag<A>, ...)
- -> typename fwd_storage<decltype(f(BOOST_SPIRIT_FAKE_CALL(A)))
- , fwd_attrib>::type
- {
- return {};
- }
- template <typename F, typename A, typename B>
- static auto do_call(F && f, fwd_tag<A>, fwd_tag<B>, ...)
- -> typename fwd_storage<
- decltype(f(BOOST_SPIRIT_FAKE_CALL(A), BOOST_SPIRIT_FAKE_CALL(B)))
- , fwd_attrib_context>::type
- {
- return {};
- }
- template <typename F, typename A, typename B, typename C>
- static auto do_call(F && f, fwd_tag<A>, fwd_tag<B>, fwd_tag<C>, ...)
- -> typename fwd_storage<
- decltype(f(BOOST_SPIRIT_FAKE_CALL(A), BOOST_SPIRIT_FAKE_CALL(B)
- , BOOST_SPIRIT_FAKE_CALL(C)))
- , fwd_attrib_context_pass>::type
- {
- return {};
- }
- // this function calls the forwarder and is responsible for
- // stripping the tail of the parameters
- template <typename F, typename... A>
- static void caller(F && f, A && ... a)
- {
- do_call(f, fwd_tag<typename std::remove_reference<A>::type>()...)
- (std::forward<F>(f), std::forward<A>(a)...);
- }
- #undef BOOST_SPIRIT_FAKE_CALL
- public:
- template <typename F, typename Attribute, typename Context>
- bool operator()(F const& f, Attribute& attr, Context& context)
- {
- bool pass = true;
- caller(f, attr, context, pass);
- return pass;
- }
- #else
- // general handler for everything not explicitly specialized below
- template <typename F, typename Attribute, typename Context>
- bool operator()(F const& f, Attribute& attr, Context& context)
- {
- bool pass = true;
- f(attr, context, pass);
- return pass;
- }
- #endif
- // handler for phoenix actors
- // If the component this action has to be invoked for is a tuple, we
- // wrap any non-fusion tuple into a fusion tuple (done by pass_attribute)
- // and pass through any fusion tuple.
- template <typename Eval, typename Attribute, typename Context>
- bool operator()(phoenix::actor<Eval> const& f
- , Attribute& attr, Context& context)
- {
- bool pass = true;
- typename pass_attribute<Component, Attribute>::type attr_wrap(attr);
- f(attr_wrap, context, pass);
- return pass;
- }
- // specializations for plain function pointers taking different number of
- // arguments
- template <typename RT, typename A0, typename A1, typename A2
- , typename Attribute, typename Context>
- bool operator()(RT(*f)(A0, A1, A2), Attribute& attr, Context& context)
- {
- bool pass = true;
- f(attr, context, pass);
- return pass;
- }
- template <typename RT, typename A0, typename A1
- , typename Attribute, typename Context>
- bool operator()(RT(*f)(A0, A1), Attribute& attr, Context& context)
- {
- f(attr, context);
- return true;
- }
- template <typename RT, typename A0, typename Attribute, typename Context>
- bool operator()(RT(*f)(A0), Attribute& attr, Context&)
- {
- f(attr);
- return true;
- }
- template <typename RT, typename Attribute, typename Context>
- bool operator()(RT(*f)(), Attribute&, Context&)
- {
- f();
- return true;
- }
- };
- }}}
- #endif
|