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

source code of boost/libs/type_erasure/include/boost/type_erasure/detail/vtable.hpp