]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /*============================================================================= |
2 | Copyright (c) 2001-2011 Joel de Guzman | |
3 | Copyright (c) 2001-2011 Hartmut Kaiser | |
4 | http://spirit.sourceforge.net/ | |
5 | ||
6 | Distributed under the Boost Software License, Version 1.0. (See accompanying | |
7 | file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
8 | =============================================================================*/ | |
9 | #if !defined(BOOST_SPIRIT_ACTION_DISPATCH_APRIL_18_2008_0720AM) | |
10 | #define BOOST_SPIRIT_ACTION_DISPATCH_APRIL_18_2008_0720AM | |
11 | ||
12 | #if defined(_MSC_VER) | |
13 | #pragma once | |
14 | #endif | |
15 | ||
16 | #include<boost/config.hpp> | |
17 | ||
18 | #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_LAMBDAS) && \ | |
19 | !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_DECLTYPE) | |
20 | #include <utility> | |
21 | #include <type_traits> | |
22 | #endif | |
23 | ||
24 | ||
25 | #include <boost/spirit/include/phoenix_core.hpp> | |
26 | #include <boost/spirit/home/support/attributes.hpp> | |
27 | ||
28 | namespace boost { namespace spirit { namespace traits | |
29 | { | |
30 | template <typename Component> | |
31 | struct action_dispatch | |
32 | { | |
33 | #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && !defined(BOOST_NO_CXX11_LAMBDAS) && \ | |
34 | !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_DECLTYPE) | |
35 | // omit function parameters without specializing for each possible | |
36 | // type of callable entity | |
37 | // many thanks to Eelis/##iso-c++ for this contribution | |
38 | ||
39 | private: | |
40 | // this will be used to pass around POD types which are safe | |
41 | // to go through the ellipsis operator (if ever used) | |
42 | template <typename> | |
43 | struct fwd_tag {}; | |
44 | ||
45 | // the first parameter is a placeholder to obtain SFINAE when | |
46 | // doing overload resolution, the second one is the actual | |
47 | // forwarder, where we can apply our implementation | |
48 | template <typename, typename T> | |
49 | struct fwd_storage { typedef T type; }; | |
50 | ||
51 | // gcc should accept fake<T>() but it prints a sorry, needs | |
52 | // a check once the bug is sorted out, use a FAKE_CALL macro for now | |
53 | template <typename T> | |
54 | T fake_call(); | |
55 | ||
56 | #define BOOST_SPIRIT_FAKE_CALL(T) (*(T*)0) | |
57 | ||
58 | // the forwarders, here we could tweak the implementation of | |
59 | // how parameters are passed to the functions, if needed | |
60 | struct fwd_none | |
61 | { | |
62 | template<typename F, typename... Rest> | |
63 | auto operator()(F && f, Rest&&...) -> decltype(f()) | |
64 | { | |
65 | return f(); | |
66 | } | |
67 | }; | |
68 | ||
69 | struct fwd_attrib | |
70 | { | |
71 | template<typename F, typename A, typename... Rest> | |
72 | auto operator()(F && f, A && a, Rest&&...) -> decltype(f(a)) | |
73 | { | |
74 | return f(a); | |
75 | } | |
76 | }; | |
77 | ||
78 | struct fwd_attrib_context | |
79 | { | |
80 | template<typename F, typename A, typename B, typename... Rest> | |
81 | auto operator()(F && f, A && a, B && b, Rest&&...) | |
82 | -> decltype(f(a, b)) | |
83 | { | |
84 | return f(a, b); | |
85 | } | |
86 | }; | |
87 | ||
88 | struct fwd_attrib_context_pass | |
89 | { | |
90 | template<typename F, typename A, typename B, typename C | |
91 | , typename... Rest> | |
92 | auto operator()(F && f, A && a, B && b, C && c, Rest&&...) | |
93 | -> decltype(f(a, b, c)) | |
94 | { | |
95 | return f(a, b, c); | |
96 | } | |
97 | }; | |
98 | ||
99 | // SFINAE for our calling syntax, the forwarders are stored based | |
100 | // on what function call gives a proper result | |
101 | // this code can probably be more generic once implementations are | |
102 | // steady | |
103 | template <typename F> | |
104 | static auto do_call(F && f, ...) | |
105 | -> typename fwd_storage<decltype(f()), fwd_none>::type | |
106 | { | |
107 | return {}; | |
108 | } | |
109 | ||
110 | template <typename F, typename A> | |
111 | static auto do_call(F && f, fwd_tag<A>, ...) | |
112 | -> typename fwd_storage<decltype(f(BOOST_SPIRIT_FAKE_CALL(A))) | |
113 | , fwd_attrib>::type | |
114 | { | |
115 | return {}; | |
116 | } | |
117 | ||
118 | template <typename F, typename A, typename B> | |
119 | static auto do_call(F && f, fwd_tag<A>, fwd_tag<B>, ...) | |
120 | -> typename fwd_storage< | |
121 | decltype(f(BOOST_SPIRIT_FAKE_CALL(A), BOOST_SPIRIT_FAKE_CALL(B))) | |
122 | , fwd_attrib_context>::type | |
123 | { | |
124 | return {}; | |
125 | } | |
126 | ||
127 | template <typename F, typename A, typename B, typename C> | |
128 | static auto do_call(F && f, fwd_tag<A>, fwd_tag<B>, fwd_tag<C>, ...) | |
129 | -> typename fwd_storage< | |
130 | decltype(f(BOOST_SPIRIT_FAKE_CALL(A), BOOST_SPIRIT_FAKE_CALL(B) | |
131 | , BOOST_SPIRIT_FAKE_CALL(C))) | |
132 | , fwd_attrib_context_pass>::type | |
133 | { | |
134 | return {}; | |
135 | } | |
136 | ||
137 | // this function calls the forwarder and is responsible for | |
138 | // stripping the tail of the parameters | |
139 | template <typename F, typename... A> | |
140 | static void caller(F && f, A && ... a) | |
141 | { | |
142 | do_call(f, fwd_tag<typename std::remove_reference<A>::type>()...) | |
143 | (std::forward<F>(f), std::forward<A>(a)...); | |
144 | } | |
145 | ||
146 | #undef BOOST_SPIRIT_FAKE_CALL | |
147 | ||
148 | public: | |
149 | template <typename F, typename Attribute, typename Context> | |
150 | bool operator()(F const& f, Attribute& attr, Context& context) | |
151 | { | |
152 | bool pass = true; | |
153 | caller(f, attr, context, pass); | |
154 | return pass; | |
155 | } | |
156 | #else | |
157 | // general handler for everything not explicitly specialized below | |
158 | template <typename F, typename Attribute, typename Context> | |
159 | bool operator()(F const& f, Attribute& attr, Context& context) | |
160 | { | |
161 | bool pass = true; | |
162 | f(attr, context, pass); | |
163 | return pass; | |
164 | } | |
165 | #endif | |
166 | ||
167 | // handler for phoenix actors | |
168 | ||
169 | // If the component this action has to be invoked for is a tuple, we | |
170 | // wrap any non-fusion tuple into a fusion tuple (done by pass_attribute) | |
171 | // and pass through any fusion tuple. | |
172 | template <typename Eval, typename Attribute, typename Context> | |
173 | bool operator()(phoenix::actor<Eval> const& f | |
174 | , Attribute& attr, Context& context) | |
175 | { | |
176 | bool pass = true; | |
177 | typename pass_attribute<Component, Attribute>::type attr_wrap(attr); | |
178 | f(attr_wrap, context, pass); | |
179 | return pass; | |
180 | } | |
181 | ||
182 | // specializations for plain function pointers taking different number of | |
183 | // arguments | |
184 | template <typename RT, typename A0, typename A1, typename A2 | |
185 | , typename Attribute, typename Context> | |
186 | bool operator()(RT(*f)(A0, A1, A2), Attribute& attr, Context& context) | |
187 | { | |
188 | bool pass = true; | |
189 | f(attr, context, pass); | |
190 | return pass; | |
191 | } | |
192 | ||
193 | template <typename RT, typename A0, typename A1 | |
194 | , typename Attribute, typename Context> | |
195 | bool operator()(RT(*f)(A0, A1), Attribute& attr, Context& context) | |
196 | { | |
197 | f(attr, context); | |
198 | return true; | |
199 | } | |
200 | ||
201 | template <typename RT, typename A0, typename Attribute, typename Context> | |
202 | bool operator()(RT(*f)(A0), Attribute& attr, Context&) | |
203 | { | |
204 | f(attr); | |
205 | return true; | |
206 | } | |
207 | ||
208 | template <typename RT, typename Attribute, typename Context> | |
209 | bool operator()(RT(*f)(), Attribute&, Context&) | |
210 | { | |
211 | f(); | |
212 | return true; | |
213 | } | |
214 | }; | |
215 | }}} | |
216 | ||
217 | #endif |