]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Boost.TypeErasure library |
2 | // | |
3 | // Copyright 2011 Steven Watanabe | |
4 | // | |
5 | // Distributed under the Boost Software License Version 1.0. (See | |
6 | // accompanying file LICENSE_1_0.txt or copy at | |
7 | // http://www.boost.org/LICENSE_1_0.txt) | |
8 | // | |
9 | // $Id$ | |
10 | ||
11 | #if !defined(BOOST_PP_IS_ITERATING) | |
12 | ||
13 | #ifndef BOOST_TYPE_ERASURE_DETAIL_VTABLE_HPP_INCLUDED | |
14 | #define BOOST_TYPE_ERASURE_DETAIL_VTABLE_HPP_INCLUDED | |
15 | ||
16 | #include <boost/config.hpp> | |
17 | #include <boost/mpl/at.hpp> | |
18 | #include <boost/mpl/size.hpp> | |
19 | #include <boost/preprocessor/cat.hpp> | |
20 | #include <boost/preprocessor/iteration/iterate.hpp> | |
21 | #include <boost/preprocessor/repetition/enum.hpp> | |
22 | #include <boost/preprocessor/repetition/enum_params.hpp> | |
23 | #include <boost/preprocessor/repetition/enum_trailing.hpp> | |
24 | #include <boost/preprocessor/repetition/enum_trailing_params.hpp> | |
25 | #include <boost/preprocessor/repetition/repeat.hpp> | |
26 | #include <boost/type_erasure/detail/rebind_placeholders.hpp> | |
27 | #include <boost/type_erasure/config.hpp> | |
28 | ||
29 | namespace boost { | |
30 | namespace type_erasure { | |
31 | namespace detail { | |
32 | ||
33 | #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_CONSTEXPR) && !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) | |
34 | ||
35 | template<class... T> | |
36 | struct stored_arg_pack; | |
37 | ||
38 | template<class It, class End, class... T> | |
39 | struct make_arg_pack_impl | |
40 | { | |
41 | typedef typename make_arg_pack_impl< | |
42 | typename ::boost::mpl::next<It>::type, | |
43 | End, | |
44 | T..., | |
45 | typename ::boost::mpl::deref<It>::type | |
46 | >::type type; | |
47 | }; | |
48 | ||
49 | template<class End, class... T> | |
50 | struct make_arg_pack_impl<End, End, T...> | |
51 | { | |
52 | typedef stored_arg_pack<T...> type; | |
53 | }; | |
54 | ||
55 | template<class Seq> | |
56 | struct make_arg_pack | |
57 | { | |
58 | typedef typename make_arg_pack_impl< | |
59 | typename ::boost::mpl::begin<Seq>::type, | |
60 | typename ::boost::mpl::end<Seq>::type | |
61 | >::type type; | |
62 | }; | |
63 | ||
64 | template<class Args> | |
65 | struct make_vtable_impl; | |
66 | ||
67 | template<class Seq> | |
68 | struct make_vtable | |
69 | { | |
70 | typedef typename ::boost::type_erasure::detail::make_vtable_impl< | |
71 | typename ::boost::type_erasure::detail::make_arg_pack<Seq>::type | |
72 | >::type type; | |
73 | }; | |
74 | ||
75 | template<class Table, class Args> | |
76 | struct make_vtable_init_impl; | |
77 | ||
78 | template<class Seq, class Table> | |
79 | struct make_vtable_init | |
80 | { | |
81 | typedef typename make_vtable_init_impl< | |
82 | Table, | |
83 | typename ::boost::type_erasure::detail::make_arg_pack<Seq>::type | |
84 | >::type type; | |
85 | }; | |
86 | ||
87 | template<class T> | |
88 | struct vtable_entry | |
89 | { | |
90 | typename T::type value; | |
91 | vtable_entry() = default; | |
92 | constexpr vtable_entry(typename T::type arg) : value(arg) {} | |
93 | }; | |
94 | ||
95 | template<class... T> | |
96 | struct compare_vtable; | |
97 | ||
98 | template<> | |
99 | struct compare_vtable<> { | |
100 | template<class S> | |
101 | static bool apply(const S& s1, const S& s2) | |
102 | { | |
103 | return true; | |
104 | } | |
105 | }; | |
106 | ||
107 | template<class T0, class... T> | |
108 | struct compare_vtable<T0, T...> { | |
109 | template<class S> | |
110 | static bool apply(const S& s1, const S& s2) | |
111 | { | |
112 | return static_cast<const vtable_entry<T0>&>(s1).value == | |
113 | static_cast<const vtable_entry<T0>&>(s2).value && | |
114 | compare_vtable<T...>::apply(s1, s2); | |
115 | } | |
116 | }; | |
117 | ||
118 | template<class... T> | |
119 | struct vtable_storage : vtable_entry<T>... | |
120 | { | |
121 | vtable_storage() = default; | |
122 | ||
123 | constexpr vtable_storage(typename T::type... arg) | |
124 | : vtable_entry<T>(arg)... {} | |
125 | ||
126 | template<class Bindings, class Src> | |
127 | void convert_from(const Src& src) | |
128 | { | |
129 | *this = vtable_storage( | |
130 | src.lookup( | |
131 | (typename ::boost::type_erasure::detail::rebind_placeholders< | |
132 | T, Bindings | |
133 | >::type*)0)...); | |
134 | } | |
135 | ||
136 | bool operator==(const vtable_storage& other) const | |
137 | { return compare_vtable<T...>::apply(*this, other); } | |
138 | ||
139 | template<class U> | |
140 | typename U::type lookup(U*) const | |
141 | { | |
142 | return static_cast<const vtable_entry<U>*>(this)->value; | |
143 | } | |
144 | }; | |
145 | ||
146 | // Provide this specialization manually. | |
147 | // gcc 4.7.2 fails to instantiate the primary template. | |
148 | template<> | |
149 | struct vtable_storage<> | |
150 | { | |
151 | vtable_storage() = default; | |
152 | ||
153 | template<class Bindings, class Src> | |
154 | void convert_from(const Src& src) {} | |
155 | ||
156 | bool operator==(const vtable_storage& other) const | |
157 | { return true; } | |
158 | }; | |
159 | ||
160 | template<class... T> | |
161 | struct make_vtable_impl<stored_arg_pack<T...> > | |
162 | { | |
163 | typedef vtable_storage<T...> type; | |
164 | }; | |
165 | ||
166 | template<class Table, class... T> | |
167 | struct vtable_init | |
168 | { | |
169 | static constexpr Table value = Table(T::value...); | |
170 | }; | |
171 | ||
172 | template<class Table, class... T> | |
173 | constexpr Table vtable_init<Table, T...>::value; | |
174 | ||
175 | template<class Table, class... T> | |
176 | struct make_vtable_init_impl<Table, stored_arg_pack<T...> > | |
177 | { | |
178 | typedef vtable_init<Table, T...> type; | |
179 | }; | |
180 | ||
181 | #else | |
182 | ||
183 | template<int N> | |
184 | struct make_vtable_impl; | |
185 | ||
186 | template<class Seq> | |
187 | struct make_vtable | |
188 | { | |
189 | typedef typename make_vtable_impl< | |
190 | (::boost::mpl::size<Seq>::value)>::template apply<Seq>::type type; | |
191 | }; | |
192 | ||
193 | template<int N> | |
194 | struct make_vtable_init_impl; | |
195 | ||
196 | template<class Seq, class Table> | |
197 | struct make_vtable_init | |
198 | { | |
199 | typedef typename make_vtable_init_impl< | |
200 | (::boost::mpl::size<Seq>::value)>::template apply<Seq, Table>::type type; | |
201 | }; | |
202 | ||
203 | #define BOOST_PP_FILENAME_1 <boost/type_erasure/detail/vtable.hpp> | |
204 | #define BOOST_PP_ITERATION_LIMITS (0, BOOST_TYPE_ERASURE_MAX_FUNCTIONS) | |
205 | #include BOOST_PP_ITERATE() | |
206 | ||
207 | #endif | |
208 | ||
209 | } | |
210 | } | |
211 | } | |
212 | ||
213 | #endif | |
214 | ||
215 | #else | |
216 | ||
217 | #define N BOOST_PP_ITERATION() | |
218 | ||
219 | #define BOOST_TYPE_ERASURE_VTABLE_ENTRY(z, n, data) \ | |
220 | typename BOOST_PP_CAT(T, n)::type BOOST_PP_CAT(t, n); \ | |
221 | typename BOOST_PP_CAT(T, n)::type lookup(BOOST_PP_CAT(T, n)*) const \ | |
222 | { \ | |
223 | return BOOST_PP_CAT(t, n); \ | |
224 | } | |
225 | ||
226 | #define BOOST_TYPE_ERASURE_VTABLE_COMPARE(z, n, data) \ | |
227 | && BOOST_PP_CAT(t, n) == other.BOOST_PP_CAT(t, n) | |
228 | ||
229 | #define BOOST_TYPE_ERASURE_VTABLE_INIT(z, n, data) \ | |
230 | BOOST_PP_CAT(data, n)::value | |
231 | ||
232 | #define BOOST_TYPE_ERASURE_AT(z, n, data) \ | |
233 | typename ::boost::mpl::at_c<data, n>::type | |
234 | ||
235 | #define BOOST_TYPE_ERASURE_CONVERT_ELEMENT(z, n, data) \ | |
236 | BOOST_PP_CAT(t, n) = src.lookup( \ | |
237 | (typename ::boost::type_erasure::detail::rebind_placeholders< \ | |
238 | BOOST_PP_CAT(T, n), Bindings \ | |
239 | >::type*)0 \ | |
240 | ); | |
241 | ||
242 | #if N != 0 | |
243 | template<BOOST_PP_ENUM_PARAMS(N, class T)> | |
244 | #else | |
245 | template<class D = void> | |
246 | #endif | |
247 | struct BOOST_PP_CAT(vtable_storage, N) | |
248 | { | |
249 | BOOST_PP_REPEAT(N, BOOST_TYPE_ERASURE_VTABLE_ENTRY, ~) | |
250 | ||
251 | template<class Bindings, class Src> | |
252 | void convert_from(const Src& src) | |
253 | { | |
254 | BOOST_PP_REPEAT(N, BOOST_TYPE_ERASURE_CONVERT_ELEMENT, ~) | |
255 | } | |
256 | ||
257 | bool operator==(const BOOST_PP_CAT(vtable_storage, N)& other) const | |
258 | { return true BOOST_PP_REPEAT(N, BOOST_TYPE_ERASURE_VTABLE_COMPARE, ~); } | |
259 | }; | |
260 | ||
261 | template<> | |
262 | struct make_vtable_impl<N> | |
263 | { | |
264 | template<class Seq> | |
265 | struct apply | |
266 | { | |
267 | typedef ::boost::type_erasure::detail::BOOST_PP_CAT(vtable_storage, N)< | |
268 | BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_AT, Seq) | |
269 | > type; | |
270 | }; | |
271 | }; | |
272 | template<class Table BOOST_PP_ENUM_TRAILING_PARAMS(N, class T)> | |
273 | struct BOOST_PP_CAT(vtable_init, N) | |
274 | { | |
275 | static const Table value; | |
276 | }; | |
277 | ||
278 | template<class Table BOOST_PP_ENUM_TRAILING_PARAMS(N, class T)> | |
279 | const Table BOOST_PP_CAT(vtable_init, N)< | |
280 | Table BOOST_PP_ENUM_TRAILING_PARAMS(N, T)>::value = | |
281 | { | |
282 | BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_VTABLE_INIT, T) | |
283 | }; | |
284 | ||
285 | template<> | |
286 | struct make_vtable_init_impl<N> | |
287 | { | |
288 | template<class Seq, class Table> | |
289 | struct apply | |
290 | { | |
291 | typedef ::boost::type_erasure::detail::BOOST_PP_CAT(vtable_init, N)< | |
292 | Table | |
293 | BOOST_PP_ENUM_TRAILING(N, BOOST_TYPE_ERASURE_AT, Seq) | |
294 | > type; | |
295 | }; | |
296 | }; | |
297 | ||
298 | #undef BOOST_TYPE_ERASURE_CONVERT_ELEMENT | |
299 | #undef BOOST_TYPE_ERASURE_AT | |
300 | #undef BOOST_TYPE_ERASURE_VTABLE_INIT | |
301 | #undef BOOST_TYPE_ERASURE_VTABLE_COMPARE | |
302 | #undef BOOST_TYPE_ERASURE_VTABLE_ENTRY | |
303 | #undef N | |
304 | ||
305 | #endif |