tuple.hpp 6.3 KB

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