import_mangled_helpers.hpp 8.2 KB

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