1 // Boost.TypeErasure library
3 // Copyright 2015 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 #ifndef BOOST_TYPE_ERASURE_DETAIL_DYNAMIC_VTABLE_HPP_INCLUDED
12 #define BOOST_TYPE_ERASURE_DETAIL_DYNAMIC_VTABLE_HPP_INCLUDED
14 #include <boost/type_erasure/detail/get_placeholders.hpp>
15 #include <boost/type_erasure/detail/rebind_placeholders.hpp>
16 #include <boost/type_erasure/detail/normalize.hpp>
17 #include <boost/type_erasure/detail/adapt_to_vtable.hpp>
18 #include <boost/type_erasure/detail/vtable.hpp>
19 #include <boost/type_erasure/static_binding.hpp>
20 #include <boost/type_erasure/register_binding.hpp>
21 #include <boost/mpl/transform.hpp>
22 #include <boost/mpl/at.hpp>
23 #include <boost/mpl/set.hpp>
24 #include <boost/mpl/for_each.hpp>
25 #include <boost/mpl/index_of.hpp>
29 namespace type_erasure {
32 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES) && !defined(BOOST_NO_CXX11_CONSTEXPR) && !defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS)
35 struct dynamic_binding_impl
37 const std::type_info * type;
41 struct append_to_key {
44 key->push_back(static_cast<const dynamic_binding_impl<P>*>(table)->type);
51 struct dynamic_vtable : dynamic_binding_impl<P>... {
52 dynamic_vtable() = default;
54 constexpr dynamic_vtable(T* ...t) : dynamic_binding_impl<P>{t}... {}
56 typename F::type lookup(F*) const {
58 typedef typename ::boost::type_erasure::detail::get_placeholders<F, ::boost::mpl::set0<> >::type placeholders;
59 typedef typename ::boost::mpl::fold<
62 ::boost::type_erasure::detail::counting_map_appender
63 >::type placeholder_map;
64 key.push_back(&typeid(typename ::boost::type_erasure::detail::rebind_placeholders<F, placeholder_map>::type));
65 ::boost::mpl::for_each<placeholders>(append_to_key<dynamic_vtable>{this, &key});
66 return reinterpret_cast<typename F::type>(lookup_function_impl(key));
68 template<class Bindings>
70 *this = dynamic_vtable(&typeid(typename boost::mpl::at<Bindings, P>::type)...);
72 template<class Bindings, class Src>
73 void convert_from(const Src& src) {
74 *this = dynamic_vtable(
75 (&src.lookup((::boost::type_erasure::typeid_<typename ::boost::mpl::at<Bindings, P>::type>*)0)())...);
80 struct make_dynamic_vtable_impl;
83 struct make_dynamic_vtable_impl<stored_arg_pack<P...> >
85 typedef dynamic_vtable<P...> type;
88 template<class PlaceholderList>
89 struct make_dynamic_vtable
90 : make_dynamic_vtable_impl<typename make_arg_pack<PlaceholderList>::type>
95 template<class Bindings>
96 struct dynamic_vtable_initializer
98 dynamic_vtable_initializer(const std::type_info**& ptr) : types(&ptr) {}
102 *(*types)++ = &typeid(typename ::boost::mpl::at<Bindings, P>::type);
104 const ::std::type_info*** types;
107 template<class Placeholders>
108 struct dynamic_vtable
110 const ::std::type_info * types[(::boost::mpl::size<Placeholders>::value)];
113 append_to_key(const std::type_info * const * t, key_type* k) : types(t), key(k) {}
117 key->push_back(types[(::boost::mpl::index_of<Placeholders, P>::type::value)]);
119 const std::type_info * const * types;
123 typename F::type lookup(F*) const {
125 typedef typename ::boost::type_erasure::detail::get_placeholders<F, ::boost::mpl::set0<> >::type placeholders;
126 typedef typename ::boost::mpl::fold<
128 ::boost::mpl::map0<>,
129 ::boost::type_erasure::detail::counting_map_appender
130 >::type placeholder_map;
131 key.push_back(&typeid(typename ::boost::type_erasure::detail::rebind_placeholders<F, placeholder_map>::type));
132 ::boost::mpl::for_each<placeholders>(append_to_key(types, &key));
133 return reinterpret_cast<typename F::type>(lookup_function_impl(key));
135 template<class Bindings>
138 const std::type_info* ptr = types;
139 ::boost::mpl::for_each<Placeholders>(dynamic_vtable_initializer<Bindings>(ptr));
141 template<class Bindings, class Src>
144 converter(const std::type_info**& t, const Src& s) : types(&t), src(&s) {}
148 *(*types)++ = &src->lookup((::boost::type_erasure::typeid_<typename ::boost::mpl::at<Bindings, P>::type>*)0)();
150 const std::type_info*** types;
153 template<class Bindings, class Src>
154 void convert_from(const Src& src) {
155 const ::std::type_info** ptr = types;
156 ::boost::mpl::for_each<Placeholders>(converter<Bindings, Src>(ptr, src));
160 template<class Placeholders>
161 struct make_dynamic_vtable
163 typedef dynamic_vtable<Placeholders> type;