insert.hpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. /// \file
  2. // Range v3 library
  3. //
  4. // Copyright Eric Niebler 2013-present
  5. //
  6. // Use, modification and distribution is subject to the
  7. // Boost Software License, Version 1.0. (See accompanying
  8. // file LICENSE_1_0.txt or copy at
  9. // http://www.boost.org/LICENSE_1_0.txt)
  10. //
  11. // Project home: https://github.com/ericniebler/range-v3
  12. //
  13. #ifndef RANGES_V3_ACTION_INSERT_HPP
  14. #define RANGES_V3_ACTION_INSERT_HPP
  15. #include <initializer_list>
  16. #include <utility>
  17. #include <range/v3/range_fwd.hpp>
  18. #include <range/v3/action/concepts.hpp>
  19. #include <range/v3/algorithm/max.hpp>
  20. #include <range/v3/iterator/common_iterator.hpp>
  21. #include <range/v3/range/traits.hpp>
  22. #include <range/v3/utility/static_const.hpp>
  23. #include <range/v3/detail/prologue.hpp>
  24. namespace ranges
  25. {
  26. /// \cond
  27. namespace adl_insert_detail
  28. {
  29. template<typename Cont, typename... Args>
  30. using insert_result_t = decltype(
  31. unwrap_reference(std::declval<Cont>()).insert(std::declval<Args>()...));
  32. template(typename Cont, typename T)(
  33. requires lvalue_container_like<Cont> AND
  34. (!range<T> && constructible_from<range_value_t<Cont>, T>)) //
  35. insert_result_t<Cont &, T> insert(Cont && cont, T && t)
  36. {
  37. return unwrap_reference(cont).insert(static_cast<T &&>(t));
  38. }
  39. template(typename Cont, typename I, typename S)(
  40. requires lvalue_container_like<Cont> AND sentinel_for<S, I> AND (!range<S>))
  41. insert_result_t<Cont &, detail::cpp17_iterator_t<I, S>,
  42. detail::cpp17_iterator_t<I, S>>
  43. insert(Cont && cont, I i, S j)
  44. {
  45. return unwrap_reference(cont).insert(detail::cpp17_iterator_t<I, S>{i},
  46. detail::cpp17_iterator_t<I, S>{j});
  47. }
  48. template(typename Cont, typename Rng)(
  49. requires lvalue_container_like<Cont> AND range<Rng>)
  50. insert_result_t<Cont &, detail::range_cpp17_iterator_t<Rng>,
  51. detail::range_cpp17_iterator_t<Rng>>
  52. insert(Cont && cont, Rng && rng)
  53. {
  54. return unwrap_reference(cont).insert(
  55. detail::range_cpp17_iterator_t<Rng>{ranges::begin(rng)},
  56. detail::range_cpp17_iterator_t<Rng>{ranges::end(rng)});
  57. }
  58. template(typename Cont, typename I, typename T)(
  59. requires lvalue_container_like<Cont> AND input_iterator<I> AND
  60. (!range<T> && constructible_from<range_value_t<Cont>, T>)) //
  61. insert_result_t<Cont &, I, T> insert(Cont && cont, I p, T && t)
  62. {
  63. return unwrap_reference(cont).insert(p, static_cast<T &&>(t));
  64. }
  65. template(typename Cont, typename I, typename N, typename T)(
  66. requires lvalue_container_like<Cont> AND input_iterator<I> AND
  67. integral<N> AND constructible_from<range_value_t<Cont>, T>)
  68. insert_result_t<Cont &, I, N, T> insert(Cont && cont, I p, N n, T && t)
  69. {
  70. return unwrap_reference(cont).insert(p, n, static_cast<T &&>(t));
  71. }
  72. /// \cond
  73. namespace detail
  74. {
  75. using ranges::detail::cpp17_iterator_t;
  76. using ranges::detail::range_cpp17_iterator_t;
  77. template(typename Cont, typename P)(
  78. requires container<Cont> AND input_iterator<P> AND
  79. random_access_reservable<Cont>)
  80. iterator_t<Cont> insert_reserve_helper(
  81. Cont & cont, P const p, range_size_t<Cont> const delta)
  82. {
  83. auto const old_size = ranges::size(cont);
  84. auto const max_size = cont.max_size();
  85. RANGES_EXPECT(delta <= max_size - old_size);
  86. auto const new_size = old_size + delta;
  87. auto const old_capacity = cont.capacity();
  88. auto const index = p - ranges::begin(cont);
  89. if(old_capacity < new_size)
  90. {
  91. auto const new_capacity =
  92. (old_capacity <= max_size / 3 * 2)
  93. ? ranges::max(old_capacity + old_capacity / 2, new_size)
  94. : max_size;
  95. cont.reserve(new_capacity);
  96. }
  97. return ranges::begin(cont) + index;
  98. }
  99. template(typename Cont, typename P, typename I, typename S)(
  100. requires sentinel_for<S, I> AND (!range<S>)) //
  101. auto insert_impl(Cont && cont, P p, I i, S j, std::false_type)
  102. -> decltype(unwrap_reference(cont).insert(
  103. p, cpp17_iterator_t<I, S>{i}, cpp17_iterator_t<I, S>{j}))
  104. {
  105. using C = cpp17_iterator_t<I, S>;
  106. return unwrap_reference(cont).insert(p, C{i}, C{j});
  107. }
  108. template(typename Cont, typename P, typename I, typename S)(
  109. requires sized_sentinel_for<S, I> AND random_access_reservable<Cont> AND
  110. (!range<S>)) //
  111. auto insert_impl(Cont && cont_, P p, I i, S j, std::true_type)
  112. -> decltype(unwrap_reference(cont_).insert(
  113. ranges::begin(unwrap_reference(cont_)), cpp17_iterator_t<I, S>{i},
  114. cpp17_iterator_t<I, S>{j}))
  115. {
  116. using C = cpp17_iterator_t<I, S>;
  117. auto && cont = unwrap_reference(cont_);
  118. auto const delta = static_cast<range_size_t<Cont>>(j - i);
  119. auto pos = insert_reserve_helper(cont, std::move(p), delta);
  120. return cont.insert(pos, C{std::move(i)}, C{std::move(j)});
  121. }
  122. template(typename Cont, typename I, typename Rng)(
  123. requires range<Rng>)
  124. auto insert_impl(Cont && cont, I p, Rng && rng, std::false_type)
  125. -> decltype(unwrap_reference(cont).insert(
  126. p, range_cpp17_iterator_t<Rng>{ranges::begin(rng)},
  127. range_cpp17_iterator_t<Rng>{ranges::end(rng)}))
  128. {
  129. using C = range_cpp17_iterator_t<Rng>;
  130. return unwrap_reference(cont).insert(
  131. p, C{ranges::begin(rng)}, C{ranges::end(rng)});
  132. }
  133. template(typename Cont, typename I, typename Rng)(
  134. requires random_access_reservable<Cont> AND sized_range<Rng>)
  135. auto insert_impl(Cont && cont_, I p, Rng && rng, std::true_type)
  136. -> decltype(unwrap_reference(cont_).insert(
  137. begin(unwrap_reference(cont_)),
  138. range_cpp17_iterator_t<Rng>{ranges::begin(rng)},
  139. range_cpp17_iterator_t<Rng>{ranges::end(rng)}))
  140. {
  141. using C = range_cpp17_iterator_t<Rng>;
  142. auto && cont = unwrap_reference(cont_);
  143. auto const delta = static_cast<range_size_t<Cont>>(ranges::size(rng));
  144. auto pos = insert_reserve_helper(cont, std::move(p), delta);
  145. return cont.insert(pos, C{ranges::begin(rng)}, C{ranges::end(rng)});
  146. }
  147. } // namespace detail
  148. /// \endcond
  149. template(typename Cont, typename P, typename I, typename S)(
  150. requires lvalue_container_like<Cont> AND input_iterator<P> AND
  151. sentinel_for<S, I> AND
  152. (!range<S>)) //
  153. auto insert(Cont && cont, P p, I i, S j) //
  154. -> decltype(detail::insert_impl(
  155. static_cast<Cont &&>(cont),
  156. static_cast<P &&>(p),
  157. static_cast<I &&>(i),
  158. static_cast<S &&>(j),
  159. meta::bool_<random_access_reservable<Cont> && //
  160. sized_sentinel_for<S, I>>{}))
  161. {
  162. return detail::insert_impl(static_cast<Cont &&>(cont),
  163. static_cast<P &&>(p),
  164. static_cast<I &&>(i),
  165. static_cast<S &&>(j),
  166. meta::bool_<random_access_reservable<Cont> &&
  167. sized_sentinel_for<S, I>>{});
  168. }
  169. template(typename Cont, typename I, typename Rng)(
  170. requires lvalue_container_like<Cont> AND input_iterator<I> AND range<Rng>)
  171. auto insert(Cont && cont, I p, Rng && rng)
  172. -> decltype(detail::insert_impl(
  173. static_cast<Cont &&>(cont), std::move(p), static_cast<Rng &&>(rng),
  174. meta::bool_<random_access_reservable<Cont> && sized_range<Rng>>{}))
  175. {
  176. return detail::insert_impl(static_cast<Cont &&>(cont),
  177. std::move(p),
  178. static_cast<Rng &&>(rng),
  179. meta::bool_<random_access_reservable<Cont> &&
  180. sized_range<Rng>>{});
  181. }
  182. struct insert_fn
  183. {
  184. template<typename Rng, typename... Args>
  185. using insert_result_t =
  186. decltype(insert(std::declval<Rng>(), std::declval<Args>()...));
  187. template(typename Rng, typename T)(
  188. requires range<Rng> AND
  189. (!range<T>) AND constructible_from<range_value_t<Rng>, T>)
  190. insert_result_t<Rng, T> operator()(Rng && rng, T && t) const
  191. {
  192. return insert(static_cast<Rng &&>(rng), static_cast<T &&>(t));
  193. }
  194. template(typename Rng, typename Rng2)(
  195. requires range<Rng> AND range<Rng2>)
  196. insert_result_t<Rng, Rng2> operator()(Rng && rng, Rng2 && rng2) const
  197. {
  198. static_assert(!is_infinite<Rng>::value,
  199. "Attempting to insert an infinite range into a container");
  200. return insert(static_cast<Rng &&>(rng), static_cast<Rng2 &&>(rng2));
  201. }
  202. template(typename Rng, typename T)(
  203. requires range<Rng>)
  204. insert_result_t<Rng, std::initializer_list<T> &> //
  205. operator()(Rng && rng, std::initializer_list<T> rng2) const
  206. {
  207. return insert(static_cast<Rng &&>(rng), rng2);
  208. }
  209. template(typename Rng, typename I, typename S)(
  210. requires range<Rng> AND sentinel_for<S, I> AND (!range<S>)) //
  211. insert_result_t<Rng, I, S> operator()(Rng && rng, I i, S j) const
  212. {
  213. return insert(static_cast<Rng &&>(rng), std::move(i), std::move(j));
  214. }
  215. template(typename Rng, typename I, typename T)(
  216. requires range<Rng> AND input_iterator<I> AND
  217. (!range<T>) AND constructible_from<range_value_t<Rng>, T>)
  218. insert_result_t<Rng, I, T> operator()(Rng && rng, I p, T && t) const
  219. {
  220. return insert(
  221. static_cast<Rng &&>(rng), std::move(p), static_cast<T &&>(t));
  222. }
  223. template(typename Rng, typename I, typename Rng2)(
  224. requires range<Rng> AND input_iterator<I> AND range<Rng2>)
  225. insert_result_t<Rng, I, Rng2> operator()(Rng && rng, I p, Rng2 && rng2) const
  226. {
  227. static_assert(!is_infinite<Rng>::value,
  228. "Attempting to insert an infinite range into a container");
  229. return insert(
  230. static_cast<Rng &&>(rng), std::move(p), static_cast<Rng2 &&>(rng2));
  231. }
  232. template(typename Rng, typename I, typename T)(
  233. requires range<Rng> AND input_iterator<I>)
  234. insert_result_t<Rng, I, std::initializer_list<T> &> //
  235. operator()(Rng && rng, I p, std::initializer_list<T> rng2) const
  236. {
  237. return insert(static_cast<Rng &&>(rng), std::move(p), rng2);
  238. }
  239. template(typename Rng, typename I, typename N, typename T)(
  240. requires range<Rng> AND input_iterator<I> AND integral<N> AND
  241. (!range<T>) AND constructible_from<range_value_t<Rng>, T>)
  242. insert_result_t<Rng, I, N, T> operator()(Rng && rng, I p, N n, T && t) const
  243. {
  244. return insert(
  245. static_cast<Rng &&>(rng), std::move(p), n, static_cast<T &&>(t));
  246. }
  247. template(typename Rng, typename P, typename I, typename S)(
  248. requires range<Rng> AND input_iterator<P> AND sentinel_for<S, I> AND
  249. (!range<S>)) //
  250. insert_result_t<Rng, P, I, S> operator()(Rng && rng, P p, I i, S j) const
  251. {
  252. return insert(
  253. static_cast<Rng &&>(rng), std::move(p), std::move(i), std::move(j));
  254. }
  255. };
  256. } // namespace adl_insert_detail
  257. /// \endcond
  258. /// \ingroup group-actions
  259. RANGES_INLINE_VARIABLE(adl_insert_detail::insert_fn, insert)
  260. namespace actions
  261. {
  262. using ranges::insert;
  263. }
  264. } // namespace ranges
  265. #include <range/v3/detail/epilogue.hpp>
  266. #endif