Mercurial > hg > vamp-build-and-test
comparison DEPENDENCIES/generic/include/boost/spirit/home/support/action_dispatch.hpp @ 16:2665513ce2d3
Add boost headers
author | Chris Cannam |
---|---|
date | Tue, 05 Aug 2014 11:11:38 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
15:663ca0da4350 | 16:2665513ce2d3 |
---|---|
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 |