xsequence.hpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. /***************************************************************************
  2. * Copyright (c) Johan Mabille, Sylvain Corlay and Wolf Vollprecht *
  3. * Copyright (c) QuantStack *
  4. * *
  5. * Distributed under the terms of the BSD 3-Clause License. *
  6. * *
  7. * The full license is in the file LICENSE, distributed with this software. *
  8. ****************************************************************************/
  9. #ifndef XTL_SEQUENCE_HPP
  10. #define XTL_SEQUENCE_HPP
  11. #include <array>
  12. #include <cstddef>
  13. #include <type_traits>
  14. #include <utility>
  15. #include <vector>
  16. #include "xtl_config.hpp"
  17. #include "xmeta_utils.hpp"
  18. namespace xtl
  19. {
  20. template <class S>
  21. S make_sequence(typename S::size_type size);
  22. template <class S>
  23. S make_sequence(typename S::size_type size, typename S::value_type v);
  24. template <class S>
  25. S make_sequence(std::initializer_list<typename S::value_type> init);
  26. template <class R, class A>
  27. decltype(auto) forward_sequence(A&& s);
  28. // equivalent to std::size(c) in c++17
  29. template <class C>
  30. constexpr auto sequence_size(const C& c) -> decltype(c.size());
  31. // equivalent to std::size(a) in c++17
  32. template <class T, std::size_t N>
  33. constexpr std::size_t sequence_size(const T (&a)[N]);
  34. /********************************
  35. * make_sequence implementation *
  36. ********************************/
  37. namespace detail
  38. {
  39. template <class S>
  40. struct sequence_builder
  41. {
  42. using value_type = typename S::value_type;
  43. using size_type = typename S::size_type;
  44. inline static S make(size_type size)
  45. {
  46. return S(size);
  47. }
  48. inline static S make(size_type size, value_type v)
  49. {
  50. return S(size, v);
  51. }
  52. inline static S make(std::initializer_list<value_type> init)
  53. {
  54. return S(init);
  55. }
  56. };
  57. template <class T, std::size_t N>
  58. struct sequence_builder<std::array<T, N>>
  59. {
  60. using sequence_type = std::array<T, N>;
  61. using value_type = typename sequence_type::value_type;
  62. using size_type = typename sequence_type::size_type;
  63. inline static sequence_type make(size_type /*size*/)
  64. {
  65. return sequence_type();
  66. }
  67. inline static sequence_type make(size_type /*size*/, value_type v)
  68. {
  69. sequence_type s;
  70. s.fill(v);
  71. return s;
  72. }
  73. inline static sequence_type make(std::initializer_list<value_type> init)
  74. {
  75. sequence_type s;
  76. std::copy(init.begin(), init.end(), s.begin());
  77. return s;
  78. }
  79. };
  80. }
  81. template <class S>
  82. inline S make_sequence(typename S::size_type size)
  83. {
  84. return detail::sequence_builder<S>::make(size);
  85. }
  86. template <class S>
  87. inline S make_sequence(typename S::size_type size, typename S::value_type v)
  88. {
  89. return detail::sequence_builder<S>::make(size, v);
  90. }
  91. template <class S>
  92. inline S make_sequence(std::initializer_list<typename S::value_type> init)
  93. {
  94. return detail::sequence_builder<S>::make(init);
  95. }
  96. /***********************************
  97. * forward_sequence implementation *
  98. ***********************************/
  99. namespace detail
  100. {
  101. template <class R, class A, class E = void>
  102. struct sequence_forwarder_impl
  103. {
  104. template <class T>
  105. static inline R forward(const T& r)
  106. {
  107. R ret;
  108. std::copy(std::begin(r), std::end(r), std::begin(ret));
  109. return ret;
  110. }
  111. };
  112. template <class R, class A>
  113. struct sequence_forwarder_impl<R, A, void_t<decltype(std::declval<R>().resize(
  114. std::declval<std::size_t>()))>>
  115. {
  116. template <class T>
  117. static inline auto forward(const T& r)
  118. {
  119. return R(std::begin(r), std::end(r));
  120. }
  121. };
  122. template <class R, class A>
  123. struct sequence_forwarder
  124. : sequence_forwarder_impl<R, A>
  125. {
  126. };
  127. template <class R>
  128. struct sequence_forwarder<R, R>
  129. {
  130. template <class T>
  131. static inline T&& forward(T&& t) noexcept
  132. {
  133. return std::forward<T>(t);
  134. }
  135. };
  136. template <class R, class A>
  137. using forwarder_type = detail::sequence_forwarder<
  138. std::decay_t<R>,
  139. std::remove_cv_t<std::remove_reference_t<A>>
  140. >;
  141. }
  142. template <class R, class A>
  143. inline decltype(auto) forward_sequence(typename std::remove_reference<A>::type& s)
  144. {
  145. using forwarder = detail::forwarder_type<R, A>;
  146. return forwarder::forward(std::forward<A>(s));
  147. }
  148. template <class R, class A>
  149. inline decltype(auto) forward_sequence(typename std::remove_reference<A>::type&& s)
  150. {
  151. using forwarder = detail::forwarder_type<R, A>;
  152. static_assert(!std::is_lvalue_reference<A>::value,
  153. "Can not forward an rvalue as an lvalue.");
  154. return forwarder::forward(std::move(s));
  155. }
  156. /********************************
  157. * sequence_size implementation *
  158. ********************************/
  159. // equivalent to std::size(c) in c++17
  160. template <class C>
  161. constexpr auto sequence_size(const C& c) -> decltype(c.size())
  162. {
  163. return c.size();
  164. }
  165. // equivalent to std::size(a) in c++17
  166. template <class T, std::size_t N>
  167. constexpr std::size_t sequence_size(const T (&)[N])
  168. {
  169. return N;
  170. }
  171. /****************************
  172. * are_equivalent_sequences *
  173. ****************************/
  174. template <class E1, class E2>
  175. inline bool are_equivalent_sequences(const E1& e1, const E2& e2)
  176. {
  177. return std::equal(e1.cbegin(), e1.cend(), e2.cbegin(), e2.cend());
  178. }
  179. }
  180. #endif