1 // Boost.TypeErasure library
3 // Copyright 2011 Steven Watanabe
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)
11 #if !defined(BOOST_PP_IS_ITERATING)
13 #ifndef BOOST_TYPE_ERASURE_DETAIL_VTABLE_HPP_INCLUDED
14 #define BOOST_TYPE_ERASURE_DETAIL_VTABLE_HPP_INCLUDED
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>
30 namespace type_erasure {
33 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_CONSTEXPR) && !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS)
36 struct stored_arg_pack;
38 template<class It, class End, class... T>
39 struct make_arg_pack_impl
41 typedef typename make_arg_pack_impl<
42 typename ::boost::mpl::next<It>::type,
45 typename ::boost::mpl::deref<It>::type
49 template<class End, class... T>
50 struct make_arg_pack_impl<End, End, T...>
52 typedef stored_arg_pack<T...> type;
58 typedef typename make_arg_pack_impl<
59 typename ::boost::mpl::begin<Seq>::type,
60 typename ::boost::mpl::end<Seq>::type
65 struct make_vtable_impl;
70 typedef typename ::boost::type_erasure::detail::make_vtable_impl<
71 typename ::boost::type_erasure::detail::make_arg_pack<Seq>::type
75 template<class Table, class Args>
76 struct make_vtable_init_impl;
78 template<class Seq, class Table>
79 struct make_vtable_init
81 typedef typename make_vtable_init_impl<
83 typename ::boost::type_erasure::detail::make_arg_pack<Seq>::type
90 typename T::type value;
91 vtable_entry() = default;
92 constexpr vtable_entry(typename T::type arg) : value(arg) {}
96 struct compare_vtable;
99 struct compare_vtable<> {
101 static bool apply(const S& s1, const S& s2)
107 template<class T0, class... T>
108 struct compare_vtable<T0, T...> {
110 static bool apply(const S& s1, const S& s2)
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);
119 struct vtable_storage : vtable_entry<T>...
121 vtable_storage() = default;
123 constexpr vtable_storage(typename T::type... arg)
124 : vtable_entry<T>(arg)... {}
126 template<class Bindings, class Src>
127 void convert_from(const Src& src)
129 *this = vtable_storage(
131 (typename ::boost::type_erasure::detail::rebind_placeholders<
136 bool operator==(const vtable_storage& other) const
137 { return compare_vtable<T...>::apply(*this, other); }
140 typename U::type lookup(U*) const
142 return static_cast<const vtable_entry<U>*>(this)->value;
146 // Provide this specialization manually.
147 // gcc 4.7.2 fails to instantiate the primary template.
149 struct vtable_storage<>
151 vtable_storage() = default;
153 template<class Bindings, class Src>
154 void convert_from(const Src& src) {}
156 bool operator==(const vtable_storage& other) const
161 struct make_vtable_impl<stored_arg_pack<T...> >
163 typedef vtable_storage<T...> type;
166 template<class Table, class... T>
169 static constexpr Table value = Table(T::value...);
172 template<class Table, class... T>
173 constexpr Table vtable_init<Table, T...>::value;
175 template<class Table, class... T>
176 struct make_vtable_init_impl<Table, stored_arg_pack<T...> >
178 typedef vtable_init<Table, T...> type;
184 struct make_vtable_impl;
189 typedef typename make_vtable_impl<
190 (::boost::mpl::size<Seq>::value)>::template apply<Seq>::type type;
194 struct make_vtable_init_impl;
196 template<class Seq, class Table>
197 struct make_vtable_init
199 typedef typename make_vtable_init_impl<
200 (::boost::mpl::size<Seq>::value)>::template apply<Seq, Table>::type type;
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()
217 #define N BOOST_PP_ITERATION()
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 \
223 return BOOST_PP_CAT(t, n); \
226 #define BOOST_TYPE_ERASURE_VTABLE_COMPARE(z, n, data) \
227 && BOOST_PP_CAT(t, n) == other.BOOST_PP_CAT(t, n)
229 #define BOOST_TYPE_ERASURE_VTABLE_INIT(z, n, data) \
230 BOOST_PP_CAT(data, n)::value
232 #define BOOST_TYPE_ERASURE_AT(z, n, data) \
233 typename ::boost::mpl::at_c<data, n>::type
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 \
243 template<BOOST_PP_ENUM_PARAMS(N, class T)>
245 template<class D = void>
247 struct BOOST_PP_CAT(vtable_storage, N)
249 BOOST_PP_REPEAT(N, BOOST_TYPE_ERASURE_VTABLE_ENTRY, ~)
251 template<class Bindings, class Src>
252 void convert_from(const Src& src)
254 BOOST_PP_REPEAT(N, BOOST_TYPE_ERASURE_CONVERT_ELEMENT, ~)
257 bool operator==(const BOOST_PP_CAT(vtable_storage, N)& other) const
258 { return true BOOST_PP_REPEAT(N, BOOST_TYPE_ERASURE_VTABLE_COMPARE, ~); }
262 struct make_vtable_impl<N>
267 typedef ::boost::type_erasure::detail::BOOST_PP_CAT(vtable_storage, N)<
268 BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_AT, Seq)
272 template<class Table BOOST_PP_ENUM_TRAILING_PARAMS(N, class T)>
273 struct BOOST_PP_CAT(vtable_init, N)
275 static const Table value;
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 =
282 BOOST_PP_ENUM(N, BOOST_TYPE_ERASURE_VTABLE_INIT, T)
286 struct make_vtable_init_impl<N>
288 template<class Seq, class Table>
291 typedef ::boost::type_erasure::detail::BOOST_PP_CAT(vtable_init, N)<
293 BOOST_PP_ENUM_TRAILING(N, BOOST_TYPE_ERASURE_AT, Seq)
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