]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/type_erasure/include/boost/type_erasure/register_binding.hpp
add subtree-ish sources for 12.0.3
[ceph.git] / ceph / src / boost / libs / type_erasure / include / boost / type_erasure / register_binding.hpp
1 // Boost.TypeErasure library
2 //
3 // Copyright 2015 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 #ifndef BOOST_TYPE_ERASURE_REGISTER_BINDING_HPP_INCLUDED
12 #define BOOST_TYPE_ERASURE_REGISTER_BINDING_HPP_INCLUDED
13
14 #include <boost/type_erasure/detail/check_map.hpp>
15 #include <boost/type_erasure/detail/get_placeholders.hpp>
16 #include <boost/type_erasure/detail/rebind_placeholders.hpp>
17 #include <boost/type_erasure/detail/normalize.hpp>
18 #include <boost/type_erasure/detail/adapt_to_vtable.hpp>
19 #include <boost/type_erasure/detail/auto_link.hpp>
20 #include <boost/type_erasure/static_binding.hpp>
21 #include <boost/mpl/transform.hpp>
22 #include <boost/mpl/remove_if.hpp>
23 #include <boost/mpl/fold.hpp>
24 #include <boost/mpl/at.hpp>
25 #include <boost/mpl/has_key.hpp>
26 #include <boost/mpl/insert.hpp>
27 #include <boost/mpl/front.hpp>
28 #include <boost/mpl/size.hpp>
29 #include <boost/mpl/equal_to.hpp>
30 #include <boost/mpl/or.hpp>
31 #include <boost/mpl/set.hpp>
32 #include <boost/mpl/map.hpp>
33 #include <boost/mpl/vector.hpp>
34 #include <boost/mpl/int.hpp>
35 #include <boost/mpl/bool.hpp>
36 #include <boost/mpl/pair.hpp>
37 #include <boost/mpl/back_inserter.hpp>
38 #include <boost/mpl/for_each.hpp>
39 #include <vector>
40 #include <typeinfo>
41
42 namespace boost {
43 namespace type_erasure {
44 namespace detail {
45
46 typedef std::vector<const std::type_info*> key_type;
47 typedef void (*value_type)();
48 BOOST_TYPE_ERASURE_DECL void register_function_impl(const key_type& key, value_type fn);
49 BOOST_TYPE_ERASURE_DECL value_type lookup_function_impl(const key_type& key);
50
51 template<class Map>
52 struct append_to_key_static {
53 append_to_key_static(key_type* k) : key(k) {}
54 template<class P>
55 void operator()(P) {
56 key->push_back(&typeid(typename ::boost::mpl::at<Map, P>::type));
57 }
58 key_type* key;
59 };
60
61 // This placeholder exists solely to create a normalized
62 // representation of a primitive concept. For the moment
63 // I'm going to be conservative and require a bijection
64 // between the original placeholders and the normalized
65 // placeholders. It should be safe to map everything
66 // to a single placeholder, though, as long as the
67 // key includes every instance of each placeholder
68 // as a separate element. i.e. we should be able to
69 // turn addable<_a, _b> into addable<_, _> and
70 // addable<_a, _a> into addable<_, _> as well if we always
71 // add typeids for both arguments to the search key.
72 template<int N>
73 struct _ : ::boost::type_erasure::placeholder {};
74
75 struct counting_map_appender
76 {
77 template<class State, class Key>
78 struct apply
79 {
80 typedef typename ::boost::mpl::insert<
81 State,
82 ::boost::mpl::pair<
83 Key,
84 ::boost::type_erasure::detail::_<
85 ::boost::mpl::size<State>::value
86 >
87 >
88 >::type type;
89 };
90 };
91
92 template<class Map>
93 struct register_function {
94 template<class F>
95 void operator()(F) {
96 key_type key;
97 typedef typename ::boost::type_erasure::detail::get_placeholders<F, ::boost::mpl::set0<> >::type placeholders;
98 typedef typename ::boost::mpl::fold<
99 placeholders,
100 ::boost::mpl::map0<>,
101 ::boost::type_erasure::detail::counting_map_appender
102 >::type placeholder_map;
103 key.push_back(&typeid(typename ::boost::type_erasure::detail::rebind_placeholders<F, placeholder_map>::type));
104 ::boost::mpl::for_each<placeholders>(append_to_key_static<Map>(&key));
105 value_type fn = reinterpret_cast<value_type>(&::boost::type_erasure::detail::rebind_placeholders<F, Map>::type::value);
106 ::boost::type_erasure::detail::register_function_impl(key, fn);
107 }
108 };
109
110 }
111
112 /**
113 * Registers a model of a concept to allow downcasting @ref any
114 * via @ref dynamic_any_cast.
115 */
116 template<class Concept, class Map>
117 void register_binding(const static_binding<Map>&)
118 {
119 typedef typename ::boost::type_erasure::detail::normalize_concept<
120 Concept
121 >::type normalized;
122 typedef typename ::boost::mpl::transform<normalized,
123 ::boost::type_erasure::detail::maybe_adapt_to_vtable< ::boost::mpl::_1>
124 >::type actual_concept;
125 typedef typename ::boost::type_erasure::detail::get_placeholder_normalization_map<
126 Concept
127 >::type placeholder_subs;
128 typedef typename ::boost::type_erasure::detail::add_deductions<Map, placeholder_subs>::type actual_map;
129 ::boost::mpl::for_each<actual_concept>(::boost::type_erasure::detail::register_function<actual_map>());
130 }
131
132 /**
133 * \overload
134 */
135 template<class Concept, class T>
136 void register_binding()
137 {
138 // Find all placeholders
139 typedef typename ::boost::type_erasure::detail::normalize_concept_impl<Concept>::type normalized;
140 typedef typename normalized::first basic;
141 typedef typename ::boost::mpl::fold<
142 basic,
143 ::boost::mpl::set0<>,
144 ::boost::type_erasure::detail::get_placeholders< ::boost::mpl::_2, ::boost::mpl::_1>
145 >::type all_placeholders;
146 // remove deduced placeholders
147 typedef typename ::boost::mpl::fold<
148 typename normalized::second,
149 ::boost::mpl::set0<>,
150 ::boost::mpl::insert< ::boost::mpl::_1, ::boost::mpl::second< ::boost::mpl::_2> >
151 >::type xtra_deduced;
152 typedef typename ::boost::mpl::remove_if<
153 all_placeholders,
154 ::boost::mpl::or_<
155 ::boost::type_erasure::detail::is_deduced< ::boost::mpl::_1>,
156 ::boost::mpl::has_key<xtra_deduced, ::boost::mpl::_1>
157 >,
158 ::boost::mpl::back_inserter< ::boost::mpl::vector0<> >
159 >::type unknown_placeholders;
160 // Bind the single remaining placeholder to T
161 BOOST_MPL_ASSERT((boost::mpl::equal_to<boost::mpl::size<unknown_placeholders>, boost::mpl::int_<1> >));
162 register_binding<Concept>(::boost::type_erasure::make_binding<
163 ::boost::mpl::map< ::boost::mpl::pair<typename ::boost::mpl::front<unknown_placeholders>::type, T> > >());
164 }
165
166 }
167 }
168
169 #endif