1 // Copyright 2015-2018 Klemens D. Morgenstern 2 // 3 // Distributed under the Boost Software License, Version 1.0. 4 // (See accompanying file LICENSE_1_0.txt 5 // or copy at http://www.boost.org/LICENSE_1_0.txt) 6 7 #ifndef BOOST_DLL_DETAIL_IMPORT_MANGLED_HELPERS_HPP_ 8 #define BOOST_DLL_DETAIL_IMPORT_MANGLED_HELPERS_HPP_ 9 10 11 #include <boost/type_traits/conditional.hpp> 12 #include <boost/type_traits/is_same.hpp> 13 #include <boost/type_traits/is_class.hpp> 14 #include <boost/type_traits/is_function.hpp> 15 #include <boost/type_traits/remove_cv.hpp> 16 17 18 #ifdef BOOST_HAS_PRAGMA_ONCE 19 # pragma once 20 #endif 21 22 namespace boost { namespace dll { namespace experimental { namespace detail { 23 24 //the following could be done by fusion, though it's simple enough to just declare it here. 25 template<class ...Args> 26 struct sequence {}; 27 28 template<class Value, class Seq> struct push_front; 29 template<class Value, class ...Args> 30 struct push_front<Value, sequence<Args...>> 31 { 32 typedef sequence<Value, Args...> type; 33 }; 34 35 template<class Lhs, class Rhs> 36 struct unqalified_is_same : 37 boost::is_same< 38 typename boost::remove_cv<Lhs>::type, 39 typename boost::remove_cv<Rhs>::type 40 > 41 { 42 }; 43 44 /* ********************************** function sequence type traits ******************************/ 45 46 //determine if it's a sequence of functions. 47 template<class T> struct is_function_seq; 48 49 //type-trait for function overloads 50 template<class Class, class...Args> struct is_function_seq<sequence<Class, Args...>> 51 : boost::conditional< 52 boost::is_function<Class>::value, 53 is_function_seq<sequence<Args...>>, 54 boost::false_type>::type 55 {}; 56 57 template<class Class> 58 struct is_function_seq<sequence<Class>> : boost::is_function<Class> 59 { 60 }; 61 62 template<> 63 struct is_function_seq<sequence<>> : boost::false_type 64 { 65 }; 66 67 /* ********************************* Function Tuple *************************** */ 68 69 //a tuple of plain functions. 70 template <class ...Ts> 71 struct function_tuple; 72 73 template <class Return, class...Args, class T2, class ...Ts> 74 struct function_tuple<Return(Args...), T2, Ts...> 75 : function_tuple<T2, Ts...> 76 { 77 Return(*f_)(Args...); 78 function_tupleboost::dll::experimental::detail::function_tuple79 constexpr function_tuple(Return(* t)(Args...), T2* t2, Ts* ... ts) 80 : function_tuple<T2, Ts...>(t2, ts...) 81 , f_(t) 82 {} 83 operator ()boost::dll::experimental::detail::function_tuple84 Return operator()(Args...args) const { 85 return (*f_)(static_cast<Args>(args)...); 86 } 87 using function_tuple<T2, Ts...>::operator(); 88 }; 89 90 template <class Return, class...Args> 91 struct function_tuple<Return(Args...)> { 92 Return(*f_)(Args...); 93 function_tupleboost::dll::experimental::detail::function_tuple94 constexpr function_tuple(Return(* t)(Args...)) 95 : f_(t) 96 {} 97 operator ()boost::dll::experimental::detail::function_tuple98 Return operator()(Args...args) const { 99 return (*f_)(static_cast<Args>(args)...); 100 } 101 }; 102 103 104 /* ********************************** MemFn sequence type traits ******************************/ 105 106 template<class Class, class Func> 107 struct mem_fn_def 108 { 109 typedef Class class_type; 110 typedef Func func_type; 111 typedef typename boost::dll::detail::get_mem_fn_type<Class, Func>::mem_fn mem_fn; 112 }; 113 114 template<class ...Args> 115 struct make_mem_fn_seq; 116 117 // B: is T1 another version of T0? 118 template<bool, class T0, class T1, class T2> 119 struct make_mem_fn_seq_getter; 120 121 template<class T0, class T1, class T2> 122 struct make_mem_fn_seq_getter<true, T0, T1, T2> 123 { 124 typedef mem_fn_def<T1, T2> type; 125 }; 126 127 template<class T0, class T1, class T2> 128 struct make_mem_fn_seq_getter<false, T0, T1, T2> 129 { 130 typedef mem_fn_def<T0, T1> type; 131 }; 132 133 template<class Class, class Signature> 134 struct make_mem_fn_seq<Class, Signature> 135 { 136 typedef mem_fn_def<Class, Signature> mem_fn; 137 typedef sequence<mem_fn> type; 138 }; 139 140 template<class Class> 141 struct make_mem_fn_seq<Class> 142 { 143 typedef sequence<> type; 144 }; 145 146 template<class T0, class T1, class T2, class ... Args> 147 struct make_mem_fn_seq<T0, T1, T2, Args...> 148 { 149 /* Since we might have ovls, it might be : 150 * Class, void(int), void(int, int) //--> just us class for both 151 * Class, const Class, void(int)//--> ovl class. 152 * 153 */ 154 static_assert(boost::is_object<T0>::value, ""); 155 typedef typename make_mem_fn_seq_getter< 156 unqalified_is_same<T0, T1>::value, T0, T1, T2>::type mem_fn_type; 157 158 typedef typename boost::conditional< 159 unqalified_is_same<T0, T1>::value, 160 make_mem_fn_seq<T1, Args...>, 161 make_mem_fn_seq<T0, T2, Args...>> ::type next; 162 163 typedef typename push_front<mem_fn_type, typename next::type>::type type; 164 }; 165 166 167 168 169 /* Ok, this needs to be documented, so here's some pseudo-code: 170 * 171 * @code 172 * 173 * bool unqalified_is_same(lhs, rhs) 174 * { 175 * return remove_cv(lhs) == remove_cv(rhs); 176 * } 177 * 178 * mem_fn make_mem_fn_seq_getter(b, cl, T2, T3) 179 * { 180 * if (b) //b means, that T2 is another version of cl, i.e. qualified 181 * return get_mem_fn_type(T2, T3); 182 * else //means that T2 is a function. 183 * return get_mem_fn_type(cl, T2); 184 * } 185 * 186 * sequence make_mem_fn_seq(type cl, type T2, type T3, types...) 187 * { 188 * mem_fn = make_mem_fn_seq_getter( 189 * unqalified_is_same(cl, T2), cl, T2, T3); 190 * 191 * next = unqalified_is_same(cl, T2) ? 192 * make_mem_fn_seq(T2, types...) //because: T2 is another version of cl, hence i use this. T3 was already consumed. 193 * : 194 * make_mem_fn_seq(Class, T3, types...) //because: T2 was a function, hence it is consumed and class remains unchanged. 195 * ; 196 * return push_front(mem_fn, next) ; 197 * }; 198 * @endcode 199 */ 200 201 202 203 template<class T, class U, class ...Args> 204 struct is_mem_fn_seq_impl 205 { 206 typedef typename boost::conditional< 207 boost::is_function<U>::value || boost::dll::experimental::detail::unqalified_is_same<T, U>::value, 208 typename is_mem_fn_seq_impl<T, Args...>::type, 209 boost::false_type>::type type; 210 }; 211 212 template<class T, class U> 213 struct is_mem_fn_seq_impl<T, U> 214 { 215 typedef typename boost::conditional< 216 boost::is_function<U>::value && boost::is_object<T>::value, 217 boost::true_type, boost::false_type>::type type; 218 }; 219 220 template<class T, class U, class Last> 221 struct is_mem_fn_seq_impl<T, U, Last> 222 { 223 typedef typename boost::conditional< 224 (boost::is_function<U>::value || boost::dll::experimental::detail::unqalified_is_same<T, U>::value) 225 && boost::is_function<Last>::value, 226 boost::true_type, boost::false_type>::type type; 227 }; 228 229 template<class T> struct is_mem_fn_seq : boost::false_type {}; 230 231 //If only two arguments are provided at all. 232 template<class T, class U> 233 struct is_mem_fn_seq<sequence<T, U>> : boost::conditional< 234 boost::is_object<T>::value && boost::is_function<U>::value, 235 boost::true_type, boost::false_type>::type 236 { 237 }; 238 239 240 template<class T, class Func, class ...Args> 241 struct is_mem_fn_seq<sequence<T, Func, Args...>> : 242 boost::conditional< 243 boost::is_class<T>::value && boost::is_function<Func>::value, 244 typename is_mem_fn_seq_impl<T, Args...>::type, 245 boost::false_type>::type {}; 246 247 248 /* ********************************** mem fn sequence tuple ******************************/ 249 250 /* A tuple of member functions 251 * Unlike for plain functions a sequence here might contain classes as well as functions. 252 */ 253 template <class ...Ts> 254 struct mem_fn_tuple; 255 256 template <class Class, class Return, class...Args, class T2, class ...Ts> 257 struct mem_fn_tuple<mem_fn_def<Class, Return(Args...)>, T2, Ts...> 258 : mem_fn_tuple<T2, Ts...> 259 { 260 typedef typename boost::dll::detail::get_mem_fn_type<Class, Return(Args...)>::mem_fn mem_fn; 261 mem_fn f_; 262 mem_fn_tupleboost::dll::experimental::detail::mem_fn_tuple263 constexpr mem_fn_tuple(mem_fn f, typename T2::mem_fn t2, typename Ts::mem_fn ... ts) 264 : mem_fn_tuple<T2, Ts...>(t2, ts...) 265 , f_(f) 266 {} 267 operator ()boost::dll::experimental::detail::mem_fn_tuple268 Return operator()(Class* const cl, Args...args) const { 269 return (cl->*f_)(static_cast<Args>(args)...); 270 } 271 using mem_fn_tuple<T2, Ts...>::operator(); 272 273 }; 274 275 template <class Class, class Return, class...Args> 276 struct mem_fn_tuple<mem_fn_def<Class, Return(Args...)>> { 277 typedef typename boost::dll::detail::get_mem_fn_type<Class, Return(Args...)>::mem_fn mem_fn; 278 mem_fn f_; 279 mem_fn_tupleboost::dll::experimental::detail::mem_fn_tuple280 constexpr mem_fn_tuple(mem_fn f) 281 : f_(f) 282 {} 283 operator ()boost::dll::experimental::detail::mem_fn_tuple284 Return operator()(Class * const cl, Args...args) const { 285 return (cl->*f_)(static_cast<Args>(args)...); 286 } 287 }; 288 289 }}}} 290 #endif /* BOOST_DLL_DETAIL_IMPORT_MANGLED_HELPERS_HPP_ */ 291