seq.hpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. // Copyright Louis Dionne 2013-2017
  2. // Distributed under the Boost Software License, Version 1.0.
  3. // (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
  4. #ifndef TEST_SUPPORT_SEQ_HPP
  5. #define TEST_SUPPORT_SEQ_HPP
  6. #include <boost/hana/fwd/at.hpp>
  7. #include <boost/hana/fwd/concept/sequence.hpp>
  8. #include <boost/hana/fwd/core/make.hpp>
  9. #include <boost/hana/fwd/drop_front.hpp>
  10. #include <boost/hana/fwd/fold_left.hpp>
  11. #include <boost/hana/fwd/is_empty.hpp>
  12. #include <boost/hana/fwd/length.hpp>
  13. #include <boost/hana/tuple.hpp>
  14. #include <boost/hana/unpack.hpp>
  15. struct Seq;
  16. template <typename Storage>
  17. struct seq_type {
  18. explicit constexpr seq_type(Storage s) : storage(s) { }
  19. Storage storage;
  20. using hana_tag = Seq;
  21. };
  22. struct seq_t {
  23. template <typename ...Xs>
  24. constexpr auto operator()(Xs&& ...xs) const {
  25. auto storage = boost::hana::make_tuple(xs...);
  26. return seq_type<decltype(storage)>(storage);
  27. }
  28. };
  29. constexpr seq_t seq{};
  30. namespace boost { namespace hana {
  31. //////////////////////////////////////////////////////////////////////////
  32. // Foldable
  33. //
  34. // Define either one to select which MCD is used:
  35. // BOOST_HANA_TEST_FOLDABLE_FOLD_LEFT_MCD
  36. // BOOST_HANA_TEST_FOLDABLE_UNPACK_MCD
  37. // BOOST_HANA_TEST_FOLDABLE_ITERABLE_MCD
  38. //
  39. // If neither is defined, the MCD used is unspecified.
  40. //////////////////////////////////////////////////////////////////////////
  41. #ifdef BOOST_HANA_TEST_FOLDABLE_FOLD_LEFT_MCD
  42. template <>
  43. struct fold_left_impl<Seq> {
  44. template <typename Xs, typename S, typename F>
  45. static constexpr auto apply(Xs xs, S s, F f) {
  46. return hana::fold_left(xs.storage, s, f);
  47. }
  48. template <typename Xs, typename F>
  49. static constexpr auto apply(Xs xs, F f) {
  50. return hana::fold_left(xs.storage, f);
  51. }
  52. };
  53. #elif defined(BOOST_HANA_TEST_FOLDABLE_ITERABLE_MCD)
  54. template <>
  55. struct length_impl<Seq> {
  56. template <typename Xs>
  57. static constexpr auto apply(Xs const& xs) {
  58. return hana::length(xs.storage);
  59. }
  60. };
  61. #else
  62. template <>
  63. struct unpack_impl<Seq> {
  64. template <typename Xs, typename F>
  65. static constexpr auto apply(Xs xs, F f)
  66. { return hana::unpack(xs.storage, f); }
  67. };
  68. #endif
  69. //////////////////////////////////////////////////////////////////////////
  70. // Iterable
  71. //////////////////////////////////////////////////////////////////////////
  72. template <>
  73. struct at_impl<Seq> {
  74. template <typename Xs, typename N>
  75. static constexpr decltype(auto) apply(Xs&& xs, N&& n) {
  76. return hana::at(static_cast<Xs&&>(xs).storage, n);
  77. }
  78. };
  79. template <>
  80. struct drop_front_impl<Seq> {
  81. template <typename Xs, typename N>
  82. static constexpr auto apply(Xs xs, N n) {
  83. return hana::unpack(hana::drop_front(xs.storage, n), ::seq);
  84. }
  85. };
  86. template <>
  87. struct is_empty_impl<Seq> {
  88. template <typename Xs>
  89. static constexpr auto apply(Xs xs) {
  90. return hana::is_empty(xs.storage);
  91. }
  92. };
  93. //////////////////////////////////////////////////////////////////////////
  94. // Sequence
  95. //////////////////////////////////////////////////////////////////////////
  96. template <>
  97. struct Sequence<Seq> {
  98. static constexpr bool value = true;
  99. };
  100. template <>
  101. struct make_impl<Seq> {
  102. template <typename ...Xs>
  103. static constexpr auto apply(Xs&& ...xs) {
  104. return ::seq(static_cast<Xs&&>(xs)...);
  105. }
  106. };
  107. }} // end namespace boost::hana
  108. #endif // !TEST_SUPPORT_SEQ_HPP