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