fork download
  1. #include <iostream>
  2. #include <sstream>
  3. #include <typeinfo>
  4. #include <cstdlib>
  5. #include <cxxabi.h>
  6.  
  7. /* general type-list */
  8. template<typename ... Types>
  9. struct type_list { typedef type_list type; };
  10.  
  11. namespace detail {
  12. std::string demangle(char const * const name) {
  13. int st;
  14. char * const p = abi::__cxa_demangle(name, 0, 0, &st);
  15. if(st != 0) return "<demangle error>";
  16.  
  17. std::string s(p);
  18. std::free(p);
  19. return s;
  20. }
  21.  
  22. /* remove lval reference */
  23. template<typename T>
  24. struct remove_lref { typedef T type; };
  25.  
  26. template<typename T>
  27. struct remove_lref<T&> { typedef T type; };
  28.  
  29. /* represents a candidate set */
  30. template<typename ... FunctionTypes>
  31. struct candidate_set;
  32.  
  33. template<typename R, typename ... Args, typename ... FunctionTypes>
  34. struct candidate_set<R(Args...), FunctionTypes...>
  35. : candidate_set<FunctionTypes...> {
  36. typedef R result_type(Args...);
  37.  
  38. using candidate_set<FunctionTypes...>::call;
  39. static result_type &call(Args...);
  40. };
  41.  
  42. template<typename R, typename ... Args>
  43. struct candidate_set<R(Args...)> {
  44. typedef R result_type(Args...);
  45. static result_type &&call(Args...);
  46. };
  47.  
  48. template<> struct candidate_set<> { };
  49.  
  50. /* return rvalue for T, T&&
  51.   return lvalue for T& */
  52. template<typename T>
  53. T &&make();
  54.  
  55. /* prepend type... */
  56. template<typename Type, typename List>
  57. struct prepend_type;
  58.  
  59. template<typename Type, typename ... Types>
  60. struct prepend_type<Type, type_list<Types...>> {
  61. typedef type_list<Type, Types...> type;
  62. };
  63.  
  64. /* append type... */
  65. template<typename Type, typename List>
  66. struct append_type;
  67.  
  68. template<typename Type, typename ... Types>
  69. struct append_type<Type, type_list<Types...>> {
  70. typedef type_list<Types..., Type> type;
  71. };
  72.  
  73. /* remove_type ... */
  74. template<typename Remove, typename List>
  75. struct remove_type;
  76.  
  77. template<typename Remove, typename ... Tail>
  78. struct remove_type<Remove, type_list<Remove, Tail...> >
  79. :remove_type<Remove, type_list<Tail...> >
  80. { };
  81.  
  82. template<typename Remove, typename Head, typename ... Tail>
  83. struct remove_type<Remove, type_list<Head, Tail...>> {
  84. typedef typename prepend_type<Head,
  85. typename remove_type<Remove, type_list<Tail...>>::type>::type type;
  86. };
  87.  
  88. template<typename Remove>
  89. struct remove_type<Remove, type_list<>> {
  90. typedef type_list<> type;
  91. };
  92.  
  93. /* returns void if the call to the candidate set fails, and the selected
  94.  * function type (lvalue ref to it) otherwise. */
  95. template<typename ... Args, typename ... Candidates>
  96. decltype(candidate_set<Candidates...>::call(make<Args>()...))
  97. check_ambiguity(type_list<Args...>, type_list<Candidates...>);
  98.  
  99. void check_ambiguity(...);
  100.  
  101. /* implementation of order_candidates */
  102. template<typename Args, typename FunctionTypes, typename Order, typename LastCalled = char>
  103. struct order_candidates_impl {
  104. static void function_call_suppression();
  105. typedef typename remove_lref<
  106. decltype(function_call_suppression(),
  107. check_ambiguity(
  108. make<Args>(),
  109. make<FunctionTypes>()))>::type winner_type;
  110.  
  111. typedef order_candidates_impl<
  112. Args,
  113. typename remove_type<winner_type, FunctionTypes>::type,
  114. typename append_type<winner_type, Order>::type, winner_type> next;
  115.  
  116. typedef typename next::type type;
  117. typedef typename next::remaining_types remaining_types;
  118. };
  119.  
  120. template<typename Args, typename FunctionTypes, typename Order>
  121. struct order_candidates_impl<Args, FunctionTypes, Order, void> {
  122. typedef typename remove_type<void, Order>::type type;
  123. typedef FunctionTypes remaining_types;
  124. };
  125.  
  126. /* get nice type string... */
  127. template<typename T>
  128. inline std::string get_type_name() {
  129. return demangle(typeid(T).name());
  130. }
  131. } // details::
  132.  
  133. template<typename Args, typename FunctionTypes>
  134. struct order_candidates
  135. : detail::order_candidates_impl<Args, FunctionTypes, type_list<>>
  136. { };
  137.  
  138. template<typename List>
  139. struct type_list2string;
  140.  
  141. template<typename Type, typename ... Types>
  142. struct type_list2string<type_list<Type, Types...> > {
  143. static void print(std::ostream &os) {
  144. os << detail::get_type_name<Type>();
  145. if(sizeof...(Types) != 0)
  146. os << ", ";
  147. type_list2string<type_list<Types...>>::print(os);
  148. }
  149. };
  150.  
  151. template<>
  152. struct type_list2string<type_list<> > {
  153. static void print(std::ostream &os) { }
  154. };
  155.  
  156. template<typename ... FunctionTypes, typename ... T>
  157. inline std::string call_candidate_set(T &&...) {
  158. typedef order_candidates<type_list<T...>, type_list<FunctionTypes...>>
  159. candidates_order;
  160. std::ostringstream order;
  161. order << " [ ";
  162. type_list2string<typename candidates_order::type>::print(order);
  163. order << " ] [ ";
  164. type_list2string<typename candidates_order::remaining_types>::print(order);
  165. order << " ]";
  166. return order.str();
  167. }
  168.  
  169. // TEST!
  170. #include <iostream>
  171. #include <cstddef>
  172.  
  173. struct Base { Base() { } Base(int) { } };
  174. struct Derived : Base {
  175. Derived() { }
  176. Derived(int) { }
  177. operator short();
  178. };
  179.  
  180. int main() {
  181. int lvalue_int = 0;
  182. std::string results[] = {
  183. // void(int), void(bool)
  184. call_candidate_set<void(int), void(bool)>('#'),
  185. // void(int)
  186. call_candidate_set<void(int), void(bool), void(short)>('#'),
  187. // void(Derived), void(Base), void(int)
  188. call_candidate_set<void(Base), void(Derived), void(int)>(Derived()),
  189. // void(char const*), void(string)
  190. call_candidate_set<void(std::string), void(char const*)>("haha"),
  191. // void(int)
  192. call_candidate_set<void(int), void(int&)>(10),
  193. // <empty>
  194. call_candidate_set<void(int), void(int const&)>(10),
  195. // void(int&&), void(int const&)
  196. call_candidate_set<void(int const&), void(int&&)>(10),
  197. // void(int const&)
  198. call_candidate_set<void(int const&), void(int&&)>(lvalue_int),
  199. // void(int&), void(int const&)
  200. call_candidate_set<void(int&), void(int const&)>(lvalue_int),
  201. // <empty>
  202. call_candidate_set<void(char const(&)[3]), void(char const*)>("12"),
  203. // void(char), void(int), void(long)
  204. call_candidate_set<void(char), void(int), void(long), void(Base), void(Derived)>('#'),
  205. call_candidate_set<void(int&&), void(int const&)>(10),
  206. call_candidate_set<void(double), void(long double), void(float), void(int)>(1.0f)
  207. };
  208. for(std::size_t i = 0; i < sizeof results / sizeof *results; i++)
  209. std::cout << results[i] << std::endl;
  210. }
  211.  
Success #stdin #stdout 0s 3004KB
stdin
Standard input is empty
stdout
 [ void (int), void (bool) ] [  ]
 [ void (int) ] [ void (bool), void (short) ]
 [ void (Derived), void (Base), void (int) ] [  ]
 [ void (char const*), void (std::string) ] [  ]
 [ void (int) ] [ void (int&) ]
 [  ] [ void (int), void (int const&) ]
 [ void (int&&), void (int const&) ] [  ]
 [ void (int const&) ] [ void (int&&) ]
 [ void (int&), void (int const&) ] [  ]
 [  ] [ void (char const (&) [3]), void (char const*) ]
 [ void (char), void (int), void (long) ] [ void (Base), void (Derived) ]
 [ void (int&&), void (int const&) ] [  ]
 [ void (float), void (double) ] [ void (long double), void (int) ]