Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

238 Zeilen
8.0 KiB

  1. #pragma once
  2. #include <cpputils/mp/core.h>
  3. #include <cpputils/mp/util/make.h>
  4. #include <cpputils/mp/util/tag_of.h>
  5. #include <cpputils/mp/intern/ebo.h>
  6. #include <cpputils/mp/intern/operators_orderable.h>
  7. #include <cpputils/mp/intern/operators_comparable.h>
  8. #include <cpputils/mp/operations/first.h>
  9. #include <cpputils/mp/operations/second.h>
  10. #include <cpputils/mp/operations/compare/less.h>
  11. #include <cpputils/mp/operations/compare/less_equal.h>
  12. #include <cpputils/mp/operations/compare/equal.h>
  13. #include <cpputils/mp/operations/logical/or.h>
  14. #include <cpputils/mp/operations/logical/and.h>
  15. #include <cpputils/mp/operations/logical/not.h>
  16. namespace utl {
  17. namespace mp {
  18. struct tag_pair { };
  19. constexpr auto make_pair = make<tag_pair>;
  20. namespace __impl
  21. {
  22. template<int>
  23. struct pair_index;
  24. }
  25. template<typename First, typename Second>
  26. struct pair :
  27. private intern::ebo<__impl::pair_index<0>, First>,
  28. private intern::ebo<__impl::pair_index<1>, Second>
  29. {
  30. using this_type = pair<First, Second>;
  31. // default constructor
  32. template<typename... dummy, typename = enable_if_c<
  33. is_constructible<First, dummy...>::value &&
  34. is_constructible<Second, dummy...>::value>>
  35. constexpr pair()
  36. : intern::ebo<__impl::pair_index<0>, First>()
  37. , intern::ebo<__impl::pair_index<1>, Second>()
  38. { }
  39. // variadic constructors
  40. template<typename... dummy, typename = enable_if_c<
  41. is_constructible<First, const First&, dummy...>::value &&
  42. is_constructible<Second, const Second&, dummy...>::value>>
  43. constexpr pair(First f, Second s)
  44. : intern::ebo<__impl::pair_index<0>, First>(f)
  45. , intern::ebo<__impl::pair_index<1>, Second>(s)
  46. { }
  47. template<typename F, typename S, typename = enable_if_c<
  48. is_convertible<F&&, First>::value &&
  49. is_convertible<S&&, Second>::value>>
  50. constexpr pair(F&& f, S&& s)
  51. : intern::ebo<__impl::pair_index<0>, First>(std::forward<F>(f))
  52. , intern::ebo<__impl::pair_index<1>, Second>(std::forward<S>(s))
  53. { }
  54. // copy and move constructor
  55. template<typename F, typename S, typename = enable_if_c<
  56. is_constructible<First, const F&>::value &&
  57. is_constructible<Second, const S&>::value &&
  58. is_convertible<const F&, First>::value &&
  59. is_convertible<const S&, Second>::value>>
  60. constexpr pair(const pair<F, S>& other)
  61. : intern::ebo<__impl::pair_index<0>, First>(mp::first(other))
  62. , intern::ebo<__impl::pair_index<1>, Second>(mp::second(other))
  63. { }
  64. template<typename F, typename S, typename = enable_if_c<
  65. is_constructible<First, const F&>::value &&
  66. is_constructible<Second, const S&>::value &&
  67. is_convertible<const F&, First>::value &&
  68. is_convertible<const S&, Second>::value>>
  69. constexpr pair(pair<F, S>&& other)
  70. : intern::ebo<__impl::pair_index<0>, First>(mp::first(std::forward<pair<F, S>>(other)))
  71. , intern::ebo<__impl::pair_index<1>, Second>(mp::second(std::forward<pair<F, S>>(other)))
  72. { }
  73. // copy and move assignment
  74. template <typename F, typename S, typename = enable_if_c<
  75. is_assignable<First&, const F&>::value &&
  76. is_assignable<Second&, const S&>::value>>
  77. constexpr pair& operator=(const pair<F, S>& other) {
  78. mp::first(*this) = mp::first(other);
  79. mp::second(*this) = mp::second(other);
  80. return *this;
  81. }
  82. template <typename F, typename S, typename = enable_if_c<
  83. is_assignable<First&, const F &>::value &&
  84. is_assignable<Second&, const S &>::value>>
  85. constexpr pair& operator=(pair<F, S>&& other) {
  86. mp::first(*this) = mp::first(std::move<pair<F, S>>(other));
  87. mp::second(*this) = mp::second(std::move<pair<F, S>>(other));
  88. return *this;
  89. }
  90. constexpr auto first() const
  91. { return mp::first(*this); }
  92. constexpr auto second() const
  93. { return mp::second(*this); }
  94. // Prevent the compiler from defining the default copy and move
  95. // constructors, which interfere with the SFINAE above.
  96. ~pair() = default;
  97. friend struct __impl::first_impl<tag_pair>;
  98. friend struct __impl::second_impl<tag_pair>;
  99. };
  100. namespace intern {
  101. template<>
  102. struct operators_comparable<tag_pair>
  103. { static constexpr bool value = true; };
  104. template<>
  105. struct operators_orderable<tag_pair>
  106. { static constexpr bool value = true; };
  107. }
  108. namespace __impl
  109. {
  110. /* tag_of */
  111. template<typename First, typename Second>
  112. struct tag_of_impl<pair<First, Second>>
  113. { using type = tag_pair; };
  114. /* make */
  115. template<>
  116. struct make_impl<tag_pair>
  117. {
  118. template<typename F, typename S>
  119. static constexpr pair<decay_type<F>, decay_type<S>> apply(F&& f, S&& s)
  120. { return { static_cast<F&&>(f), static_cast<S&&>(s) }; }
  121. };
  122. /* first */
  123. template<>
  124. struct first_impl<tag_pair>
  125. {
  126. using type = int;
  127. template<typename First, typename Second>
  128. static constexpr auto apply(pair<First, Second>& p)
  129. {
  130. return intern::ebo_get<pair_index<0>>(
  131. static_cast<intern::ebo<pair_index<0>, First>&>(p)
  132. );
  133. }
  134. template<typename First, typename Second>
  135. static constexpr auto apply(pair<First, Second>&& p)
  136. {
  137. return intern::ebo_get<pair_index<0>>(
  138. static_cast<intern::ebo<pair_index<0>, First>&&>(p)
  139. );
  140. }
  141. template<typename First, typename Second>
  142. static constexpr auto apply(const pair<First, Second>& p)
  143. {
  144. return intern::ebo_get<pair_index<0>>(
  145. static_cast<const intern::ebo<pair_index<0>, First>&>(p)
  146. );
  147. }
  148. };
  149. /* second */
  150. template<>
  151. struct second_impl<tag_pair>
  152. {
  153. template<typename First, typename Second>
  154. static constexpr auto apply(pair<First, Second>& p)
  155. {
  156. return intern::ebo_get<pair_index<1>>(
  157. static_cast<intern::ebo<pair_index<1>, Second>&>(p)
  158. );
  159. }
  160. template<typename First, typename Second>
  161. static constexpr auto apply(pair<First, Second>&& p)
  162. {
  163. return intern::ebo_get<pair_index<1>>(
  164. static_cast<intern::ebo<pair_index<1>, Second>&&>(p)
  165. );
  166. }
  167. template<typename First, typename Second>
  168. static constexpr auto apply(const pair<First, Second>& p)
  169. {
  170. return intern::ebo_get<pair_index<1>>(
  171. static_cast<const intern::ebo<pair_index<1>, Second>&>(p)
  172. );
  173. }
  174. };
  175. /* equal */
  176. template<>
  177. struct equal_impl<tag_pair, tag_pair>
  178. {
  179. template<typename L, typename R>
  180. static constexpr auto apply(const L& l, const R& r)
  181. {
  182. return and_(
  183. equal(first(l), first(r)),
  184. equal(second(l), second(r)));
  185. }
  186. };
  187. /* less */
  188. template<>
  189. struct less_impl<tag_pair, tag_pair>
  190. {
  191. template<typename L, typename R>
  192. static constexpr auto apply(const L& l, const R& r)
  193. {
  194. return or_(
  195. less(first(l), first(r)),
  196. and_(
  197. less_equal(first (l), first (r)),
  198. less (second(l), second(r))
  199. )
  200. );
  201. }
  202. };
  203. }
  204. }
  205. }