pair.hpp 7.7 KB

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