tuple.hpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. /*!
  2. @file
  3. Adapts `std::tuple` for use with Hana.
  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_EXT_STD_TUPLE_HPP
  9. #define BOOST_HANA_EXT_STD_TUPLE_HPP
  10. #include <boost/hana/bool.hpp>
  11. #include <boost/hana/config.hpp>
  12. #include <boost/hana/detail/decay.hpp>
  13. #include <boost/hana/fwd/at.hpp>
  14. #include <boost/hana/fwd/core/make.hpp>
  15. #include <boost/hana/fwd/core/tag_of.hpp>
  16. #include <boost/hana/fwd/drop_front.hpp>
  17. #include <boost/hana/fwd/empty.hpp>
  18. #include <boost/hana/fwd/flatten.hpp>
  19. #include <boost/hana/fwd/front.hpp>
  20. #include <boost/hana/fwd/is_empty.hpp>
  21. #include <boost/hana/fwd/length.hpp>
  22. #include <boost/hana/fwd/lift.hpp>
  23. #include <boost/hana/integral_constant.hpp>
  24. #include <cstddef>
  25. #include <tuple>
  26. #include <type_traits>
  27. #include <utility>
  28. #ifdef BOOST_HANA_DOXYGEN_INVOKED
  29. namespace std {
  30. //! @ingroup group-ext-std
  31. //! Adapter for `std::tuple`s.
  32. //!
  33. //!
  34. //! Modeled concepts
  35. //! ----------------
  36. //! A `std::tuple` is a model of the `Sequence` concept, and all the
  37. //! concepts it refines. That makes it essentially the same as a Hana
  38. //! tuple, although the complexity of some operations might differ from
  39. //! that of Hana's tuple.
  40. //!
  41. //! @include example/ext/std/tuple.cpp
  42. template <typename ...T>
  43. struct tuple { };
  44. }
  45. #endif
  46. BOOST_HANA_NAMESPACE_BEGIN
  47. namespace ext { namespace std { struct tuple_tag; }}
  48. template <typename ...Xs>
  49. struct tag_of<std::tuple<Xs...>> {
  50. using type = ext::std::tuple_tag;
  51. };
  52. //////////////////////////////////////////////////////////////////////////
  53. // make
  54. //////////////////////////////////////////////////////////////////////////
  55. template <>
  56. struct make_impl<ext::std::tuple_tag> {
  57. template <typename ...Xs>
  58. static constexpr decltype(auto) apply(Xs&& ...xs) {
  59. return std::make_tuple(static_cast<Xs&&>(xs)...);
  60. }
  61. };
  62. //////////////////////////////////////////////////////////////////////////
  63. // Applicative
  64. //////////////////////////////////////////////////////////////////////////
  65. template <>
  66. struct lift_impl<ext::std::tuple_tag> {
  67. template <typename X>
  68. static constexpr auto apply(X&& x) {
  69. return std::tuple<typename detail::decay<X>::type>{
  70. static_cast<X&&>(x)};
  71. }
  72. };
  73. //////////////////////////////////////////////////////////////////////////
  74. // Monad
  75. //////////////////////////////////////////////////////////////////////////
  76. template <>
  77. struct flatten_impl<ext::std::tuple_tag> {
  78. template <typename Xs, std::size_t ...i>
  79. static constexpr decltype(auto)
  80. flatten_helper(Xs&& xs, std::index_sequence<i...>) {
  81. return std::tuple_cat(std::get<i>(static_cast<Xs&&>(xs))...);
  82. }
  83. template <typename Xs>
  84. static constexpr decltype(auto) apply(Xs&& xs) {
  85. using Raw = typename std::remove_reference<Xs>::type;
  86. constexpr std::size_t Length = std::tuple_size<Raw>::value;
  87. return flatten_helper(static_cast<Xs&&>(xs),
  88. std::make_index_sequence<Length>{});
  89. }
  90. };
  91. //////////////////////////////////////////////////////////////////////////
  92. // MonadPlus
  93. //////////////////////////////////////////////////////////////////////////
  94. template <>
  95. struct empty_impl<ext::std::tuple_tag> {
  96. static constexpr auto apply()
  97. { return std::tuple<>{}; }
  98. };
  99. //////////////////////////////////////////////////////////////////////////
  100. // Iterable
  101. //////////////////////////////////////////////////////////////////////////
  102. template <>
  103. struct front_impl<ext::std::tuple_tag> {
  104. template <typename Xs>
  105. static constexpr decltype(auto) apply(Xs&& xs) {
  106. return std::get<0>(static_cast<Xs&&>(xs));
  107. }
  108. };
  109. template <>
  110. struct drop_front_impl<ext::std::tuple_tag> {
  111. template <std::size_t n, typename Xs, std::size_t ...i>
  112. static constexpr auto drop_front_helper(Xs&& xs, std::index_sequence<i...>) {
  113. return std::make_tuple(
  114. hana::at_c<n + i>(static_cast<Xs&&>(xs))...
  115. );
  116. }
  117. template <typename Xs, typename N>
  118. static constexpr auto apply(Xs&& xs, N const&) {
  119. using Raw = typename std::remove_reference<Xs>::type;
  120. constexpr std::size_t n = N::value;
  121. constexpr auto len = std::tuple_size<Raw>::value;
  122. return drop_front_helper<n>(static_cast<Xs&&>(xs),
  123. std::make_index_sequence<(n < len ? len - n : 0)>{});
  124. }
  125. };
  126. template <>
  127. struct is_empty_impl<ext::std::tuple_tag> {
  128. template <typename ...Xs>
  129. static constexpr auto apply(std::tuple<Xs...> const&)
  130. { return hana::bool_c<sizeof...(Xs) == 0>; }
  131. };
  132. template <>
  133. struct at_impl<ext::std::tuple_tag> {
  134. template <typename Xs, typename N>
  135. static constexpr decltype(auto) apply(Xs&& xs, N const&) {
  136. constexpr std::size_t index = N::value;
  137. return std::get<index>(static_cast<Xs&&>(xs));
  138. }
  139. };
  140. //////////////////////////////////////////////////////////////////////////
  141. // Foldable
  142. //////////////////////////////////////////////////////////////////////////
  143. template <>
  144. struct length_impl<ext::std::tuple_tag> {
  145. template <typename ...Xs>
  146. static constexpr auto apply(std::tuple<Xs...> const&) {
  147. return hana::size_c<sizeof...(Xs)>;
  148. }
  149. };
  150. //////////////////////////////////////////////////////////////////////////
  151. // Sequence
  152. //////////////////////////////////////////////////////////////////////////
  153. template <>
  154. struct Sequence<ext::std::tuple_tag> {
  155. static constexpr bool value = true;
  156. };
  157. BOOST_HANA_NAMESPACE_END
  158. #endif // !BOOST_HANA_EXT_STD_TUPLE_HPP