pair.hpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. /*!
  2. @file
  3. Defines `boost::hana::pair`.
  4. Copyright Louis Dionne 2013-2022
  5. Distributed under the Boost Software License, Version 1.0.
  6. (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
  7. */
  8. #ifndef BOOST_HANA_PAIR_HPP
  9. #define BOOST_HANA_PAIR_HPP
  10. #include <boost/hana/fwd/pair.hpp>
  11. #include <boost/hana/config.hpp>
  12. #include <boost/hana/detail/decay.hpp>
  13. #include <boost/hana/detail/ebo.hpp>
  14. #include <boost/hana/detail/intrinsics.hpp>
  15. #include <boost/hana/detail/operators/adl.hpp>
  16. #include <boost/hana/detail/operators/comparable.hpp>
  17. #include <boost/hana/detail/operators/orderable.hpp>
  18. #include <boost/hana/fwd/core/make.hpp>
  19. #include <boost/hana/fwd/first.hpp>
  20. #include <boost/hana/fwd/second.hpp>
  21. #include <type_traits>
  22. #include <utility>
  23. namespace boost { namespace hana {
  24. namespace detail {
  25. template <int> struct pix; // pair index
  26. }
  27. //////////////////////////////////////////////////////////////////////////
  28. // pair
  29. //////////////////////////////////////////////////////////////////////////
  30. //! @cond
  31. template <typename First, typename Second>
  32. #ifdef BOOST_HANA_WORKAROUND_MSVC_EMPTYBASE
  33. struct __declspec(empty_bases) pair : detail::operators::adl<pair<First, Second>>
  34. #else
  35. struct pair : detail::operators::adl<pair<First, Second>>
  36. #endif
  37. , private detail::ebo<detail::pix<0>, First>
  38. , private detail::ebo<detail::pix<1>, Second>
  39. {
  40. // Default constructor
  41. template <typename ...dummy, typename = typename std::enable_if<
  42. BOOST_HANA_TT_IS_CONSTRUCTIBLE(First, dummy...) &&
  43. BOOST_HANA_TT_IS_CONSTRUCTIBLE(Second, dummy...)
  44. >::type>
  45. constexpr pair()
  46. : detail::ebo<detail::pix<0>, First>()
  47. , detail::ebo<detail::pix<1>, Second>()
  48. { }
  49. // Variadic constructors
  50. template <typename ...dummy, typename = typename std::enable_if<
  51. BOOST_HANA_TT_IS_CONSTRUCTIBLE(First, First const&, dummy...) &&
  52. BOOST_HANA_TT_IS_CONSTRUCTIBLE(Second, Second const&, dummy...)
  53. >::type>
  54. constexpr pair(First const& fst, Second const& snd)
  55. : detail::ebo<detail::pix<0>, First>(fst)
  56. , detail::ebo<detail::pix<1>, Second>(snd)
  57. { }
  58. template <typename T, typename U, typename = typename std::enable_if<
  59. BOOST_HANA_TT_IS_CONVERTIBLE(T&&, First) &&
  60. BOOST_HANA_TT_IS_CONVERTIBLE(U&&, Second)
  61. >::type>
  62. constexpr pair(T&& t, U&& u)
  63. : detail::ebo<detail::pix<0>, First>(static_cast<T&&>(t))
  64. , detail::ebo<detail::pix<1>, Second>(static_cast<U&&>(u))
  65. { }
  66. // Possibly converting copy and move constructors
  67. template <typename T, typename U, typename = typename std::enable_if<
  68. BOOST_HANA_TT_IS_CONSTRUCTIBLE(First, T const&) &&
  69. BOOST_HANA_TT_IS_CONSTRUCTIBLE(Second, U const&) &&
  70. BOOST_HANA_TT_IS_CONVERTIBLE(T const&, First) &&
  71. BOOST_HANA_TT_IS_CONVERTIBLE(U const&, Second)
  72. >::type>
  73. constexpr pair(pair<T, U> const& other)
  74. : detail::ebo<detail::pix<0>, First>(hana::first(other))
  75. , detail::ebo<detail::pix<1>, Second>(hana::second(other))
  76. { }
  77. template <typename T, typename U, typename = typename std::enable_if<
  78. BOOST_HANA_TT_IS_CONSTRUCTIBLE(First, T&&) &&
  79. BOOST_HANA_TT_IS_CONSTRUCTIBLE(Second, U&&) &&
  80. BOOST_HANA_TT_IS_CONVERTIBLE(T&&, First) &&
  81. BOOST_HANA_TT_IS_CONVERTIBLE(U&&, Second)
  82. >::type>
  83. constexpr pair(pair<T, U>&& other)
  84. : detail::ebo<detail::pix<0>, First>(hana::first(static_cast<pair<T, U>&&>(other)))
  85. , detail::ebo<detail::pix<1>, Second>(hana::second(static_cast<pair<T, U>&&>(other)))
  86. { }
  87. // Copy and move assignment
  88. template <typename T, typename U, typename = typename std::enable_if<
  89. BOOST_HANA_TT_IS_ASSIGNABLE(First&, T const&) &&
  90. BOOST_HANA_TT_IS_ASSIGNABLE(Second&, U const&)
  91. >::type>
  92. constexpr pair& operator=(pair<T, U> const& other) {
  93. hana::first(*this) = hana::first(other);
  94. hana::second(*this) = hana::second(other);
  95. return *this;
  96. }
  97. template <typename T, typename U, typename = typename std::enable_if<
  98. BOOST_HANA_TT_IS_ASSIGNABLE(First&, T&&) &&
  99. BOOST_HANA_TT_IS_ASSIGNABLE(Second&, U&&)
  100. >::type>
  101. constexpr pair& operator=(pair<T, U>&& other) {
  102. hana::first(*this) = hana::first(static_cast<pair<T, U>&&>(other));
  103. hana::second(*this) = hana::second(static_cast<pair<T, U>&&>(other));
  104. return *this;
  105. }
  106. // Prevent the compiler from defining the default copy and move
  107. // constructors, which interfere with the SFINAE above.
  108. ~pair() = default;
  109. friend struct first_impl<pair_tag>;
  110. friend struct second_impl<pair_tag>;
  111. template <typename F, typename S> friend struct pair;
  112. };
  113. //! @endcond
  114. template <typename First, typename Second>
  115. struct tag_of<pair<First, Second>> {
  116. using type = pair_tag;
  117. };
  118. //////////////////////////////////////////////////////////////////////////
  119. // Operators
  120. //////////////////////////////////////////////////////////////////////////
  121. namespace detail {
  122. template <>
  123. struct comparable_operators<pair_tag> {
  124. static constexpr bool value = true;
  125. };
  126. template <>
  127. struct orderable_operators<pair_tag> {
  128. static constexpr bool value = true;
  129. };
  130. }
  131. //////////////////////////////////////////////////////////////////////////
  132. // Product
  133. //////////////////////////////////////////////////////////////////////////
  134. template <>
  135. struct make_impl<pair_tag> {
  136. template <typename F, typename S>
  137. static constexpr pair<
  138. typename detail::decay<F>::type,
  139. typename detail::decay<S>::type
  140. > apply(F&& f, S&& s) {
  141. return {static_cast<F&&>(f), static_cast<S&&>(s)};
  142. }
  143. };
  144. template <>
  145. struct first_impl<pair_tag> {
  146. template <typename First, typename Second>
  147. static constexpr decltype(auto) apply(hana::pair<First, Second>& p) {
  148. return detail::ebo_get<detail::pix<0>>(
  149. static_cast<detail::ebo<detail::pix<0>, First>&>(p)
  150. );
  151. }
  152. template <typename First, typename Second>
  153. static constexpr decltype(auto) apply(hana::pair<First, Second> const& p) {
  154. return detail::ebo_get<detail::pix<0>>(
  155. static_cast<detail::ebo<detail::pix<0>, First> const&>(p)
  156. );
  157. }
  158. template <typename First, typename Second>
  159. static constexpr decltype(auto) apply(hana::pair<First, Second>&& p) {
  160. return detail::ebo_get<detail::pix<0>>(
  161. static_cast<detail::ebo<detail::pix<0>, First>&&>(p)
  162. );
  163. }
  164. };
  165. template <>
  166. struct second_impl<pair_tag> {
  167. template <typename First, typename Second>
  168. static constexpr decltype(auto) apply(hana::pair<First, Second>& p) {
  169. return detail::ebo_get<detail::pix<1>>(
  170. static_cast<detail::ebo<detail::pix<1>, Second>&>(p)
  171. );
  172. }
  173. template <typename First, typename Second>
  174. static constexpr decltype(auto) apply(hana::pair<First, Second> const& p) {
  175. return detail::ebo_get<detail::pix<1>>(
  176. static_cast<detail::ebo<detail::pix<1>, Second> const&>(p)
  177. );
  178. }
  179. template <typename First, typename Second>
  180. static constexpr decltype(auto) apply(hana::pair<First, Second>&& p) {
  181. return detail::ebo_get<detail::pix<1>>(
  182. static_cast<detail::ebo<detail::pix<1>, Second>&&>(p)
  183. );
  184. }
  185. };
  186. }} // end namespace boost::hana
  187. #endif // !BOOST_HANA_PAIR_HPP