You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

302 lines
13KB

  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. namespace ranges
  24. {
  25. /// \cond
  26. namespace adl_insert_detail
  27. {
  28. template<typename Cont, typename... Args>
  29. using insert_result_t = decltype(
  30. unwrap_reference(std::declval<Cont>()).insert(std::declval<Args>()...));
  31. template<typename Cont, typename T>
  32. auto insert(Cont && cont, T && t) -> CPP_ret(insert_result_t<Cont &, T>)( //
  33. requires lvalue_container_like<Cont> &&
  34. (!range<T> && constructible_from<range_value_t<Cont>, T>))
  35. {
  36. return unwrap_reference(cont).insert(static_cast<T &&>(t));
  37. }
  38. template<typename Cont, typename I, typename S>
  39. auto insert(Cont && cont, I i, S j)
  40. -> CPP_ret(insert_result_t<Cont &, detail::cpp17_iterator_t<I, S>,
  41. detail::cpp17_iterator_t<I, S>>)( //
  42. requires lvalue_container_like<Cont> && sentinel_for<S, I> && (!range<S>))
  43. {
  44. return unwrap_reference(cont).insert(detail::cpp17_iterator_t<I, S>{i},
  45. detail::cpp17_iterator_t<I, S>{j});
  46. }
  47. template<typename Cont, typename Rng>
  48. auto insert(Cont && cont, Rng && rng)
  49. -> CPP_ret(insert_result_t<Cont &, detail::range_cpp17_iterator_t<Rng>,
  50. detail::range_cpp17_iterator_t<Rng>>)( //
  51. requires lvalue_container_like<Cont> && range<Rng>)
  52. {
  53. return unwrap_reference(cont).insert(
  54. detail::range_cpp17_iterator_t<Rng>{ranges::begin(rng)},
  55. detail::range_cpp17_iterator_t<Rng>{ranges::end(rng)});
  56. }
  57. template<typename Cont, typename I, typename T>
  58. auto insert(Cont && cont, I p, T && t)
  59. -> CPP_ret(insert_result_t<Cont &, I, T>)( //
  60. requires lvalue_container_like<Cont> && input_iterator<I> &&
  61. (!range<T> && constructible_from<range_value_t<Cont>, 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. auto insert(Cont && cont, I p, N n, T && t)
  67. -> CPP_ret(insert_result_t<Cont &, I, N, T>)( //
  68. requires lvalue_container_like<Cont> && input_iterator<I> &&
  69. integral<N> && constructible_from<range_value_t<Cont>, T>)
  70. {
  71. return unwrap_reference(cont).insert(p, n, static_cast<T &&>(t));
  72. }
  73. /// \cond
  74. namespace detail
  75. {
  76. using ranges::detail::cpp17_iterator_t;
  77. using ranges::detail::range_cpp17_iterator_t;
  78. template<typename Cont, typename P>
  79. auto insert_reserve_helper(Cont & cont, P const p,
  80. range_size_t<Cont> const delta)
  81. -> CPP_ret(iterator_t<Cont>)( //
  82. requires container<Cont> && input_iterator<P> &&
  83. random_access_reservable<Cont>)
  84. {
  85. auto const old_size = ranges::size(cont);
  86. auto const max_size = cont.max_size();
  87. RANGES_EXPECT(delta <= max_size - old_size);
  88. auto const new_size = old_size + delta;
  89. auto const old_capacity = cont.capacity();
  90. auto const index = p - ranges::begin(cont);
  91. if(old_capacity < new_size)
  92. {
  93. auto const new_capacity =
  94. (old_capacity <= max_size / 3 * 2)
  95. ? ranges::max(old_capacity + old_capacity / 2, new_size)
  96. : max_size;
  97. cont.reserve(new_capacity);
  98. }
  99. return ranges::begin(cont) + index;
  100. }
  101. template<typename Cont, typename P, typename I, typename S>
  102. auto insert_impl(Cont && cont, P p, I i, S j, std::false_type)
  103. -> CPP_ret(decltype(unwrap_reference(cont).insert(
  104. p, cpp17_iterator_t<I, S>{i}, cpp17_iterator_t<I, S>{j})))( //
  105. requires sentinel_for<S, I> && (!range<S>))
  106. {
  107. using C = cpp17_iterator_t<I, S>;
  108. return unwrap_reference(cont).insert(p, C{i}, C{j});
  109. }
  110. template<typename Cont, typename P, typename I, typename S>
  111. auto insert_impl(Cont && cont_, P p, I i, S j, std::true_type)
  112. -> CPP_ret(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. requires sized_sentinel_for<S, I> && random_access_reservable<Cont> &&
  116. (!range<S>))
  117. {
  118. using C = cpp17_iterator_t<I, S>;
  119. auto && cont = unwrap_reference(cont_);
  120. auto const delta = static_cast<range_size_t<Cont>>(j - i);
  121. auto pos = insert_reserve_helper(cont, std::move(p), delta);
  122. return cont.insert(pos, C{std::move(i)}, C{std::move(j)});
  123. }
  124. template<typename Cont, typename I, typename Rng>
  125. auto insert_impl(Cont && cont, I p, Rng && rng, std::false_type)
  126. -> CPP_ret(decltype(unwrap_reference(cont).insert(
  127. p, range_cpp17_iterator_t<Rng>{ranges::begin(rng)},
  128. range_cpp17_iterator_t<Rng>{ranges::end(rng)})))( //
  129. requires range<Rng>)
  130. {
  131. using C = range_cpp17_iterator_t<Rng>;
  132. return unwrap_reference(cont).insert(
  133. p, C{ranges::begin(rng)}, C{ranges::end(rng)});
  134. }
  135. template<typename Cont, typename I, typename Rng>
  136. auto insert_impl(Cont && cont_, I p, Rng && rng, std::true_type)
  137. -> CPP_ret(decltype(unwrap_reference(cont_).insert(
  138. begin(unwrap_reference(cont_)),
  139. range_cpp17_iterator_t<Rng>{ranges::begin(rng)},
  140. range_cpp17_iterator_t<Rng>{ranges::end(rng)})))( //
  141. requires random_access_reservable<Cont> && sized_range<Rng>)
  142. {
  143. using C = range_cpp17_iterator_t<Rng>;
  144. auto && cont = unwrap_reference(cont_);
  145. auto const delta = static_cast<range_size_t<Cont>>(ranges::size(rng));
  146. auto pos = insert_reserve_helper(cont, std::move(p), delta);
  147. return cont.insert(pos, C{ranges::begin(rng)}, C{ranges::end(rng)});
  148. }
  149. } // namespace detail
  150. /// \endcond
  151. template<typename Cont, typename P, typename I, typename S>
  152. auto insert(Cont && cont, P p, I i, S j) -> CPP_ret(decltype(detail::insert_impl(
  153. static_cast<Cont &&>(cont), std::move(p), std::move(i), std::move(j),
  154. meta::bool_<random_access_reservable<Cont> &&
  155. sized_sentinel_for<S, I>>{})))( //
  156. requires lvalue_container_like<Cont> && input_iterator<P> &&
  157. sentinel_for<S, I> &&
  158. (!range<S>))
  159. {
  160. return detail::insert_impl(static_cast<Cont &&>(cont),
  161. std::move(p),
  162. std::move(i),
  163. std::move(j),
  164. meta::bool_ < random_access_reservable<Cont> &&
  165. sized_sentinel_for<S, I>> {});
  166. }
  167. template<typename Cont, typename I, typename Rng>
  168. auto insert(Cont && cont, I p, Rng && rng)
  169. -> CPP_ret(decltype(detail::insert_impl(
  170. static_cast<Cont &&>(cont), std::move(p), static_cast<Rng &&>(rng),
  171. meta::bool_<random_access_reservable<Cont> && sized_range<Rng>>{})))( //
  172. requires lvalue_container_like<Cont> && input_iterator<I> && range<Rng>)
  173. {
  174. return detail::insert_impl(static_cast<Cont &&>(cont),
  175. std::move(p),
  176. static_cast<Rng &&>(rng),
  177. meta::bool_ < random_access_reservable<Cont> &&
  178. sized_range<Rng>> {});
  179. }
  180. struct insert_fn
  181. {
  182. template<typename Rng, typename... Args>
  183. using insert_result_t =
  184. decltype(insert(std::declval<Rng>(), std::declval<Args>()...));
  185. template<typename Rng, typename T>
  186. auto operator()(Rng && rng, T && t) const
  187. -> CPP_ret(insert_result_t<Rng, T>)( //
  188. requires range<Rng> &&
  189. (!range<T>)&&constructible_from<range_value_t<Rng>, T>)
  190. {
  191. return insert(static_cast<Rng &&>(rng), static_cast<T &&>(t));
  192. }
  193. template<typename Rng, typename Rng2>
  194. auto operator()(Rng && rng, Rng2 && rng2) const
  195. -> CPP_ret(insert_result_t<Rng, Rng2>)( //
  196. requires range<Rng> && range<Rng2>)
  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. auto operator()(Rng && rng, std::initializer_list<T> rng2) const
  204. -> CPP_ret(insert_result_t<Rng, std::initializer_list<T> &>)( //
  205. requires range<Rng>)
  206. {
  207. return insert(static_cast<Rng &&>(rng), rng2);
  208. }
  209. template<typename Rng, typename I, typename S>
  210. auto operator()(Rng && rng, I i, S j) const
  211. -> CPP_ret(insert_result_t<Rng, I, S>)( //
  212. requires range<Rng> && sentinel_for<S, I> && (!range<S>))
  213. {
  214. return insert(static_cast<Rng &&>(rng), std::move(i), std::move(j));
  215. }
  216. template<typename Rng, typename I, typename T>
  217. auto operator()(Rng && rng, I p, T && t) const
  218. -> CPP_ret(insert_result_t<Rng, I, T>)( //
  219. requires range<Rng> && input_iterator<I> &&
  220. (!range<T>)&&constructible_from<range_value_t<Rng>, T>)
  221. {
  222. return insert(
  223. static_cast<Rng &&>(rng), std::move(p), static_cast<T &&>(t));
  224. }
  225. template<typename Rng, typename I, typename Rng2>
  226. auto operator()(Rng && rng, I p, Rng2 && rng2) const
  227. -> CPP_ret(insert_result_t<Rng, I, Rng2>)( //
  228. requires range<Rng> && input_iterator<I> && range<Rng2>)
  229. {
  230. static_assert(!is_infinite<Rng>::value,
  231. "Attempting to insert an infinite range into a container");
  232. return insert(
  233. static_cast<Rng &&>(rng), std::move(p), static_cast<Rng2 &&>(rng2));
  234. }
  235. template<typename Rng, typename I, typename T>
  236. auto operator()(Rng && rng, I p, std::initializer_list<T> rng2) const
  237. -> CPP_ret(insert_result_t<Rng, I, std::initializer_list<T> &>)( //
  238. requires range<Rng> && input_iterator<I>)
  239. {
  240. return insert(static_cast<Rng &&>(rng), std::move(p), rng2);
  241. }
  242. template<typename Rng, typename I, typename N, typename T>
  243. auto operator()(Rng && rng, I p, N n, T && t) const
  244. -> CPP_ret(insert_result_t<Rng, I, N, T>)( //
  245. requires range<Rng> && input_iterator<I> && integral<N> &&
  246. (!range<T>)&&constructible_from<range_value_t<Rng>, T>)
  247. {
  248. return insert(
  249. static_cast<Rng &&>(rng), std::move(p), n, static_cast<T &&>(t));
  250. }
  251. template<typename Rng, typename P, typename I, typename S>
  252. auto operator()(Rng && rng, P p, I i, S j) const
  253. -> CPP_ret(insert_result_t<Rng, P, I, S>)( //
  254. requires range<Rng> && input_iterator<P> && sentinel_for<S, I> &&
  255. (!range<S>))
  256. {
  257. return insert(
  258. static_cast<Rng &&>(rng), std::move(p), std::move(i), std::move(j));
  259. }
  260. };
  261. } // namespace adl_insert_detail
  262. /// \endcond
  263. /// \ingroup group-actions
  264. RANGES_INLINE_VARIABLE(adl_insert_detail::insert_fn, insert)
  265. namespace actions
  266. {
  267. using ranges::insert;
  268. }
  269. } // namespace ranges
  270. #endif