fork download
  1. #include <iostream>
  2. #include <tuple>
  3.  
  4. namespace adv
  5. {
  6. namespace type
  7. {
  8. using index_t = unsigned;
  9. }
  10.  
  11. namespace utility
  12. {
  13. template <typename ... Types>
  14. struct type_carrier
  15. {
  16. using carrier_type = type_carrier<Types ... >;
  17.  
  18. static constexpr type::index_t size()
  19. {
  20. return static_cast<type::index_t>(sizeof ... (Types));
  21. }
  22. };
  23.  
  24. template <unsigned ... Indices>
  25. struct index_carrier
  26. {
  27. using carrier_type = index_carrier<Indices ... >;
  28.  
  29. static constexpr type::index_t size()
  30. {
  31. return static_cast<type::index_t>(sizeof ... (Indices));
  32. }
  33. };
  34.  
  35. namespace detail
  36. {
  37. template <typename, typename>
  38. struct type_carrier_contains;
  39.  
  40. template <typename Type, typename Current>
  41. struct type_carrier_contains<type_carrier<Current>, Type>
  42. {
  43. enum : bool { value = std::is_same<Current, Type>::value };
  44. };
  45.  
  46. template <typename Type, typename Current, typename Next, typename ... Rest>
  47. struct type_carrier_contains<type_carrier<Current, Next, Rest ... >, Type>
  48. {
  49. enum : bool { value = type_carrier_contains<type_carrier<Current>, Type>::value || type_carrier_contains<type_carrier<Next, Rest ... >, Type>::value };
  50. };
  51.  
  52. template <typename, unsigned>
  53. struct index_carrier_contains;
  54.  
  55. template <unsigned Index, unsigned Current>
  56. struct index_carrier_contains<index_carrier<Current>, Index>
  57. {
  58. enum : bool { value = Current == Index };
  59. };
  60.  
  61. template <unsigned Index, unsigned Current, unsigned Next, unsigned ... Rest>
  62. struct index_carrier_contains<index_carrier<Current, Next, Rest ... >, Index>
  63. {
  64. enum : bool { value = index_carrier_contains<index_carrier<Current>, Index>::value || index_carrier_contains<index_carrier<Next, Rest ... >, Index>::value };
  65. };
  66. }
  67.  
  68. template <typename, typename>
  69. struct carrier_contains;
  70.  
  71. template <typename ... Types, typename Current>
  72. struct carrier_contains<type_carrier<Types ... >, type_carrier<Current>>
  73. {
  74. enum : bool { value = detail::type_carrier_contains<type_carrier<Types ... >, Current>::value };
  75. };
  76.  
  77. template <typename ... Types, typename Current, typename Next, typename ... Rest>
  78. struct carrier_contains<type_carrier<Types ... >, type_carrier<Current, Next, Rest ... >>
  79. {
  80. enum : bool { value = detail::type_carrier_contains<type_carrier<Types ... >, Current>::value&& carrier_contains<type_carrier<Types ... >, type_carrier<Next, Rest ... >>::value };
  81. };
  82.  
  83. template <unsigned ... Indices, unsigned Current>
  84. struct carrier_contains<index_carrier<Indices ... >, index_carrier<Current>>
  85. {
  86. enum : bool { value = detail::index_carrier_contains<index_carrier<Indices ... >, Current>::value };
  87. };
  88.  
  89. template <unsigned ... Indices, unsigned Current, unsigned Next, unsigned ... Rest>
  90. struct carrier_contains<index_carrier<Indices ... >, index_carrier<Current, Next, Rest ... >>
  91. {
  92. enum : bool { value = detail::index_carrier_contains<index_carrier<Indices ... >, Current>::value&& carrier_contains<index_carrier<Indices ... >, index_carrier<Next, Rest ... >>::value };
  93. };
  94.  
  95. // ----------------------------------------->
  96.  
  97. namespace detail {
  98. template <typename, typename>
  99. struct type_carrier_count;
  100.  
  101. template <typename Type>
  102. struct type_carrier_count<type_carrier<>, Type>
  103. {
  104. enum : type::index_t { value = 0 };
  105. };
  106.  
  107. template <typename Type, typename Current>
  108. struct type_carrier_count<type_carrier<Current>, Type>
  109. {
  110. enum : type::index_t { value = std::is_same<Current, Type>::value ? 1 : 0 };
  111. };
  112.  
  113. template <typename Type, typename Current, typename ... Rest>
  114. struct type_carrier_count<type_carrier<Current, Rest ... >, Type>
  115. {
  116. enum : type::index_t { value = type_carrier_count<type_carrier<Current>, Type>::value + type_carrier_count<type_carrier<Rest ... >, Type>::value };
  117. };
  118.  
  119. template <typename, unsigned>
  120. struct index_carrier_count;
  121.  
  122. template <unsigned Index>
  123. struct index_carrier_count<index_carrier<>, Index>
  124. {
  125. enum : type::index_t { value = 0 };
  126. };
  127.  
  128. template <unsigned Index, unsigned Current>
  129. struct index_carrier_count<index_carrier<Current>, Index>
  130. {
  131. enum : type::index_t { value = (Current == Index) ? 1 : 0 };
  132. };
  133.  
  134. template <unsigned Index, unsigned Current, unsigned ... Rest>
  135. struct index_carrier_count<index_carrier<Current, Rest ... >, Index>
  136. {
  137. enum : type::index_t { value = index_carrier_count<index_carrier<Current>, Index>::value + index_carrier_count<index_carrier<Rest ... >, Index>::value };
  138. };
  139. }
  140.  
  141. template <typename, typename>
  142. struct carrier_count;
  143.  
  144. template <typename ... Types, typename Current>
  145. struct carrier_count<type_carrier<Types ... >, type_carrier<Current>>
  146. {
  147. enum : type::index_t { value = detail::type_carrier_count<type_carrier<Types ... >, Current>::value };
  148. };
  149.  
  150. template <unsigned ... Indices, unsigned Current>
  151. struct carrier_count<index_carrier<Indices ... >, index_carrier<Current>>
  152. {
  153. enum : type::index_t { value = detail::index_carrier_contains<index_carrier<Indices ... >, Current>::value };
  154. };
  155.  
  156. // ----------------------------------------->
  157.  
  158. namespace detail {
  159. template <typename, typename, unsigned, unsigned, unsigned>
  160. struct type_carrier_nth_index;
  161.  
  162. template <typename Type, unsigned Index, unsigned Count, unsigned Target>
  163. struct type_carrier_nth_index<type_carrier<>, Type, Index, Count, Target>
  164. {
  165. enum : type::index_t { value = 0 };
  166. };
  167.  
  168. template <typename Type, typename Current, unsigned Index, unsigned Count, unsigned Target>
  169. struct type_carrier_nth_index<type_carrier<Current>, Type, Index, Count, Target>
  170. {
  171. enum : type::index_t { value = ((Count == Target) && std::is_same<Current, Type>::value) ? Index : 0 };
  172. };
  173.  
  174. template <typename Type, typename Current, typename ... Rest, unsigned Index, unsigned Count, unsigned Target>
  175. struct type_carrier_nth_index<type_carrier<Current, Rest ... >, Type, Index, Count, Target>
  176. {
  177. enum : type::index_t
  178. {
  179. value = type_carrier_nth_index<type_carrier<Current>, Type, Index, Count, Target>::value + type_carrier_nth_index<type_carrier<Rest ... >, Type, Index + 1, Count + (std::is_same<Current, Type>::value ? 1 : 0), Target>::value
  180. };
  181. };
  182.  
  183. template <typename, unsigned, unsigned, unsigned, unsigned>
  184. struct index_carrier_nth_index;
  185.  
  186. template <unsigned Other, unsigned Index, unsigned Count, unsigned Target>
  187. struct index_carrier_nth_index<index_carrier<>, Other, Index, Count, Target>
  188. {
  189. enum : type::index_t { value = 0 };
  190. };
  191.  
  192. template <unsigned Other, unsigned Current, unsigned Index, unsigned Count, unsigned Target>
  193. struct index_carrier_nth_index<index_carrier<Current>, Other, Index, Count, Target>
  194. {
  195. enum : type::index_t { value = ((Count == Target) && (Current == Other)) ? Index : 0 };
  196. };
  197.  
  198. template <unsigned Other, unsigned Current, unsigned ... Rest, unsigned Index, unsigned Count, unsigned Target>
  199. struct index_carrier_nth_index<index_carrier<Current, Rest ... >, Other, Index, Count, Target>
  200. {
  201. enum : type::index_t { value = index_carrier_nth_index<index_carrier<Current>, Other, Index, Count, Target>::value + index_carrier_nth_index<index_carrier<Rest ... >, Other, Index + 1, Count + (Current == Other ? 1 : 0), Target>::value };
  202. };
  203. }
  204.  
  205. template <typename, typename, unsigned>
  206. struct carrier_nth_index;
  207.  
  208. template <typename ... Types, typename Current, unsigned Number>
  209. struct carrier_nth_index<type_carrier<Types ... >, Current, Number>
  210. {
  211. static_assert(carrier_count<type_carrier<Types ... >, type_carrier<Current>>::value > Number, "Type carrier does not contain type with this index!");
  212. enum : type::index_t { value = detail::type_carrier_nth_index<type_carrier<Types ... >, Current, 0, 0, Number>::value };
  213. };
  214.  
  215. template <unsigned ... Indices, unsigned Current, unsigned Number>
  216. struct carrier_nth_index<index_carrier<Indices ... >, index_carrier<Current>, Number>
  217. {
  218. static_assert(carrier_count<index_carrier<Indices ... >, index_carrier<Current>>::value > Number, "Index carrier does not contain index with this index!");
  219. enum : type::index_t { value = detail::index_carrier_nth_index<index_carrier<Indices ... >, Current, 0, 0, Number>::value };
  220. };
  221.  
  222. namespace detail
  223. {
  224. template <typename>
  225. struct parameters;
  226.  
  227. template <typename Return, typename Type, typename ... Arguments>
  228. struct parameters<Return(Type::*)(Arguments ...)>
  229. {
  230. using type = type_carrier<std::decay_t<Arguments> ... >;
  231. };
  232.  
  233. template <typename Return, typename Type, typename ... Arguments>
  234. struct parameters<Return(Type::*)(Arguments ...) const>
  235. {
  236. using type = type_carrier<std::decay_t<Arguments> ... >;
  237. };
  238. }
  239.  
  240. template <typename Type>
  241. using parameters_t = typename detail::parameters<decltype(&Type::operator ())>::type;
  242.  
  243. namespace detail
  244. {
  245. template <typename, typename, typename, typename>
  246. struct map_parameters_to_carrier;
  247.  
  248. template <typename Parameter, typename ... Types>
  249. struct map_parameters_to_carrier<type_carrier<Parameter>, type_carrier<Types ... >, index_carrier<>, type_carrier<>>
  250. {
  251. using type = index_carrier<carrier_nth_index<type_carrier<Types ... >, Parameter, 0>::value>;
  252. };
  253.  
  254. template <typename Parameter, typename ... Types, unsigned ... Indices, typename ... Visited>
  255. struct map_parameters_to_carrier<type_carrier<Parameter>, type_carrier<Types ... >, index_carrier<Indices ... >, type_carrier<Visited ... >>
  256. {
  257. using type = index_carrier<Indices ... , carrier_nth_index<type_carrier<Types ... >, Parameter, carrier_count<type_carrier<Visited ... >, type_carrier<Parameter>>::value>::value>;
  258. };
  259.  
  260. template <typename Current, typename ... Parameters, typename ... Types>
  261. struct map_parameters_to_carrier<type_carrier<Current, Parameters ... >, type_carrier<Types ... >, index_carrier<>, type_carrier<>>
  262. {
  263. using type = typename map_parameters_to_carrier<type_carrier<Parameters ... >, type_carrier<Types ... >, index_carrier<carrier_nth_index<type_carrier<Types ... >, Current, 0>::value>, type_carrier<Current>>::type;
  264. };
  265.  
  266. template <typename Current, typename ... Parameters, typename ... Types, unsigned ... Indices, typename ... Visited>
  267. struct map_parameters_to_carrier<type_carrier<Current, Parameters ... >, type_carrier<Types ... >, index_carrier<Indices ... >, type_carrier<Visited ... >>
  268. {
  269. using type = typename map_parameters_to_carrier<type_carrier<Parameters ... >, type_carrier<Types ... >, index_carrier<Indices ... , carrier_nth_index<type_carrier<Types ... >, Current, carrier_count<type_carrier<Visited ... >, type_carrier<Current>>::value>::value>, type_carrier<Visited ... , Current>>::type;
  270. };
  271. }
  272.  
  273. template <typename Parameters, typename Carrier>
  274. using map_parameters_to_carrier_t = typename detail::map_parameters_to_carrier<Parameters, Carrier, index_carrier<>, type_carrier<>>::type;
  275. }
  276.  
  277. namespace detail
  278. {
  279. template <typename ... Types, unsigned ... Indices, typename Functor>
  280. decltype(auto) this_with(std::tuple<Types ... > & object, utility::index_carrier<Indices ... >, Functor&& functor)
  281. {
  282. return functor(std::get<Indices>(object) ...);
  283. }
  284. }
  285.  
  286. template <typename ... Types, typename Functor>
  287. decltype(auto) apply(std::tuple<Types ... > & object, Functor && functor)
  288. {
  289. static_assert(utility::carrier_contains<utility::type_carrier<Types ... >, utility::parameters_t<Functor>>::value, "This tuple does not contain one or more of these types!");
  290.  
  291. constexpr auto parameters = utility::map_parameters_to_carrier_t<utility::parameters_t<Functor>, utility::type_carrier<Types ... >>
  292. {
  293. // ...
  294. };
  295.  
  296. return detail::this_with(object, parameters, std::forward<Functor>(functor));
  297. }
  298. }
  299.  
  300. int main() {
  301. auto x = std::make_tuple(1, 2, 3, 4, 5, 6, 7, 8.0, 9, 10, 11, 33, 13, 14, 15.f, 16, 17, 18, 2);
  302.  
  303. std::cout << adv::apply(x, [](float a, double b, int c, int d) {
  304.  
  305. std::cout << a << std::endl;
  306. std::cout << b << std::endl;
  307. std::cout << c << std::endl;
  308. std::cout << d << std::endl;
  309.  
  310. return d;
  311. });
  312. }
Success #stdin #stdout 0s 4264KB
stdin
Standard input is empty
stdout
15
8
1
2
2