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