Horizon
insert.hpp
Go to the documentation of this file.
1 // 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 
14 #ifndef RANGES_V3_ACTION_INSERT_HPP
15 #define RANGES_V3_ACTION_INSERT_HPP
16 
17 #include <initializer_list>
18 #include <utility>
19 
20 #include <range/v3/range_fwd.hpp>
21 
26 #include <range/v3/utility/static_const.hpp>
27 
28 #include <range/v3/detail/prologue.hpp>
29 
30 namespace ranges
31 {
33  namespace adl_insert_detail
34  {
35  template<typename Cont, typename... Args>
36  using insert_result_t = decltype(
37  unwrap_reference(std::declval<Cont>()).insert(std::declval<Args>()...));
38 
39  template(typename Cont, typename T)(
40  requires lvalue_container_like<Cont> AND
41  (!range<T> && constructible_from<range_value_t<Cont>, T>)) //
42  insert_result_t<Cont &, T> insert(Cont && cont, T && t)
43  {
44  return unwrap_reference(cont).insert(static_cast<T &&>(t));
45  }
46 
47  template(typename Cont, typename I, typename S)(
48  requires lvalue_container_like<Cont> AND sentinel_for<S, I> AND (!range<S>))
49  insert_result_t<Cont &, detail::cpp17_iterator_t<I, S>,
50  detail::cpp17_iterator_t<I, S>>
51  insert(Cont && cont, I i, S j)
52  {
53  return unwrap_reference(cont).insert(detail::cpp17_iterator_t<I, S>{i},
54  detail::cpp17_iterator_t<I, S>{j});
55  }
56 
57  template(typename Cont, typename Rng)(
58  requires lvalue_container_like<Cont> AND range<Rng>)
59  insert_result_t<Cont &, detail::range_cpp17_iterator_t<Rng>,
60  detail::range_cpp17_iterator_t<Rng>>
61  insert(Cont && cont, Rng && rng)
62  {
63  return unwrap_reference(cont).insert(
64  detail::range_cpp17_iterator_t<Rng>{ranges::begin(rng)},
65  detail::range_cpp17_iterator_t<Rng>{ranges::end(rng)});
66  }
67 
68  template(typename Cont, typename I, typename T)(
69  requires lvalue_container_like<Cont> AND input_iterator<I> AND
70  (!range<T> && constructible_from<range_value_t<Cont>, T>)) //
71  insert_result_t<Cont &, I, T> insert(Cont && cont, I p, T && t)
72  {
73  return unwrap_reference(cont).insert(p, static_cast<T &&>(t));
74  }
75 
76  template(typename Cont, typename I, typename N, typename T)(
77  requires lvalue_container_like<Cont> AND input_iterator<I> AND
78  integral<N> AND constructible_from<range_value_t<Cont>, T>)
79  insert_result_t<Cont &, I, N, T> insert(Cont && cont, I p, N n, T && t)
80  {
81  return unwrap_reference(cont).insert(p, n, static_cast<T &&>(t));
82  }
83 
85  namespace detail
86  {
87  using ranges::detail::cpp17_iterator_t;
88  using ranges::detail::range_cpp17_iterator_t;
89 
90  template(typename Cont, typename P)(
91  requires container<Cont> AND input_iterator<P> AND
92  random_access_reservable<Cont>)
93  iterator_t<Cont> insert_reserve_helper(
94  Cont & cont, P const p, range_size_t<Cont> const delta)
95  {
96  auto const old_size = ranges::size(cont);
97  auto const max_size = cont.max_size();
98  RANGES_EXPECT(delta <= max_size - old_size);
99  auto const new_size = old_size + delta;
100  auto const old_capacity = cont.capacity();
101  auto const index = p - ranges::begin(cont);
102  if(old_capacity < new_size)
103  {
104  auto const new_capacity =
105  (old_capacity <= max_size / 3 * 2)
106  ? ranges::max(old_capacity + old_capacity / 2, new_size)
107  : max_size;
108  cont.reserve(new_capacity);
109  }
110  return ranges::begin(cont) + index;
111  }
112 
113  template(typename Cont, typename P, typename I, typename S)(
114  requires sentinel_for<S, I> AND (!range<S>)) //
115  auto insert_impl(Cont && cont, P p, I i, S j, std::false_type)
116  -> decltype(unwrap_reference(cont).insert(
117  p, cpp17_iterator_t<I, S>{i}, cpp17_iterator_t<I, S>{j}))
118  {
119  using C = cpp17_iterator_t<I, S>;
120  return unwrap_reference(cont).insert(p, C{i}, C{j});
121  }
122 
123  template(typename Cont, typename P, typename I, typename S)(
124  requires sized_sentinel_for<S, I> AND random_access_reservable<Cont> AND
125  (!range<S>)) //
126  auto insert_impl(Cont && cont_, P p, I i, S j, std::true_type)
127  -> decltype(unwrap_reference(cont_).insert(
128  ranges::begin(unwrap_reference(cont_)), cpp17_iterator_t<I, S>{i},
129  cpp17_iterator_t<I, S>{j}))
130  {
131  using C = cpp17_iterator_t<I, S>;
132  auto && cont = unwrap_reference(cont_);
133  auto const delta = static_cast<range_size_t<Cont>>(j - i);
134  auto pos = insert_reserve_helper(cont, std::move(p), delta);
135  return cont.insert(pos, C{std::move(i)}, C{std::move(j)});
136  }
137 
138  template(typename Cont, typename I, typename Rng)(
139  requires range<Rng>)
140  auto insert_impl(Cont && cont, I p, Rng && rng, std::false_type)
141  -> decltype(unwrap_reference(cont).insert(
142  p, range_cpp17_iterator_t<Rng>{ranges::begin(rng)},
143  range_cpp17_iterator_t<Rng>{ranges::end(rng)}))
144  {
145  using C = range_cpp17_iterator_t<Rng>;
146  return unwrap_reference(cont).insert(
147  p, C{ranges::begin(rng)}, C{ranges::end(rng)});
148  }
149 
150  template(typename Cont, typename I, typename Rng)(
151  requires random_access_reservable<Cont> AND sized_range<Rng>)
152  auto insert_impl(Cont && cont_, I p, Rng && rng, std::true_type)
153  -> decltype(unwrap_reference(cont_).insert(
154  begin(unwrap_reference(cont_)),
155  range_cpp17_iterator_t<Rng>{ranges::begin(rng)},
156  range_cpp17_iterator_t<Rng>{ranges::end(rng)}))
157  {
158  using C = range_cpp17_iterator_t<Rng>;
159  auto && cont = unwrap_reference(cont_);
160  auto const delta = static_cast<range_size_t<Cont>>(ranges::size(rng));
161  auto pos = insert_reserve_helper(cont, std::move(p), delta);
162  return cont.insert(pos, C{ranges::begin(rng)}, C{ranges::end(rng)});
163  }
164  } // namespace detail
166 
167  template(typename Cont, typename P, typename I, typename S)(
168  requires lvalue_container_like<Cont> AND input_iterator<P> AND
169  sentinel_for<S, I> AND
170  (!range<S>)) //
171  auto insert(Cont && cont, P p, I i, S j) //
172  -> decltype(detail::insert_impl(
173  static_cast<Cont &&>(cont),
174  static_cast<P &&>(p),
175  static_cast<I &&>(i),
176  static_cast<S &&>(j),
177  meta::bool_<random_access_reservable<Cont> && //
178  sized_sentinel_for<S, I>>{}))
179  {
180  return detail::insert_impl(static_cast<Cont &&>(cont),
181  static_cast<P &&>(p),
182  static_cast<I &&>(i),
183  static_cast<S &&>(j),
184  meta::bool_<random_access_reservable<Cont> &&
185  sized_sentinel_for<S, I>>{});
186  }
187 
188  template(typename Cont, typename I, typename Rng)(
189  requires lvalue_container_like<Cont> AND input_iterator<I> AND range<Rng>)
190  auto insert(Cont && cont, I p, Rng && rng)
191  -> decltype(detail::insert_impl(
192  static_cast<Cont &&>(cont), std::move(p), static_cast<Rng &&>(rng),
193  meta::bool_<random_access_reservable<Cont> && sized_range<Rng>>{}))
194  {
195  return detail::insert_impl(static_cast<Cont &&>(cont),
196  std::move(p),
197  static_cast<Rng &&>(rng),
198  meta::bool_<random_access_reservable<Cont> &&
199  sized_range<Rng>>{});
200  }
201 
202  struct insert_fn
203  {
204  template<typename Rng, typename... Args>
205  using insert_result_t =
206  decltype(insert(std::declval<Rng>(), std::declval<Args>()...));
207 
208  template(typename Rng, typename T)(
209  requires range<Rng> AND
210  (!range<T>) AND constructible_from<range_value_t<Rng>, T>)
211  insert_result_t<Rng, T> operator()(Rng && rng, T && t) const
212  {
213  return insert(static_cast<Rng &&>(rng), static_cast<T &&>(t));
214  }
215 
216  template(typename Rng, typename Rng2)(
217  requires range<Rng> AND range<Rng2>)
218  insert_result_t<Rng, Rng2> operator()(Rng && rng, Rng2 && rng2) const
219  {
220  static_assert(!is_infinite<Rng>::value,
221  "Attempting to insert an infinite range into a container");
222  return insert(static_cast<Rng &&>(rng), static_cast<Rng2 &&>(rng2));
223  }
224 
225  template(typename Rng, typename T)(
226  requires range<Rng>)
227  insert_result_t<Rng, std::initializer_list<T> &> //
228  operator()(Rng && rng, std::initializer_list<T> rng2) const
229  {
230  return insert(static_cast<Rng &&>(rng), rng2);
231  }
232 
233  template(typename Rng, typename I, typename S)(
234  requires range<Rng> AND sentinel_for<S, I> AND (!range<S>)) //
235  insert_result_t<Rng, I, S> operator()(Rng && rng, I i, S j) const
236  {
237  return insert(static_cast<Rng &&>(rng), std::move(i), std::move(j));
238  }
239 
240  template(typename Rng, typename I, typename T)(
241  requires range<Rng> AND input_iterator<I> AND
242  (!range<T>) AND constructible_from<range_value_t<Rng>, T>)
243  insert_result_t<Rng, I, T> operator()(Rng && rng, I p, T && t) const
244  {
245  return insert(
246  static_cast<Rng &&>(rng), std::move(p), static_cast<T &&>(t));
247  }
248 
249  template(typename Rng, typename I, typename Rng2)(
250  requires range<Rng> AND input_iterator<I> AND range<Rng2>)
251  insert_result_t<Rng, I, Rng2> operator()(Rng && rng, I p, Rng2 && rng2) const
252  {
253  static_assert(!is_infinite<Rng>::value,
254  "Attempting to insert an infinite range into a container");
255  return insert(
256  static_cast<Rng &&>(rng), std::move(p), static_cast<Rng2 &&>(rng2));
257  }
258 
259  template(typename Rng, typename I, typename T)(
260  requires range<Rng> AND input_iterator<I>)
261  insert_result_t<Rng, I, std::initializer_list<T> &> //
262  operator()(Rng && rng, I p, std::initializer_list<T> rng2) const
263  {
264  return insert(static_cast<Rng &&>(rng), std::move(p), rng2);
265  }
266 
267  template(typename Rng, typename I, typename N, typename T)(
268  requires range<Rng> AND input_iterator<I> AND integral<N> AND
269  (!range<T>) AND constructible_from<range_value_t<Rng>, T>)
270  insert_result_t<Rng, I, N, T> operator()(Rng && rng, I p, N n, T && t) const
271  {
272  return insert(
273  static_cast<Rng &&>(rng), std::move(p), n, static_cast<T &&>(t));
274  }
275 
276  template(typename Rng, typename P, typename I, typename S)(
277  requires range<Rng> AND input_iterator<P> AND sentinel_for<S, I> AND
278  (!range<S>)) //
279  insert_result_t<Rng, P, I, S> operator()(Rng && rng, P p, I i, S j) const
280  {
281  return insert(
282  static_cast<Rng &&>(rng), std::move(p), std::move(i), std::move(j));
283  }
284  };
285  } // namespace adl_insert_detail
287 
289  RANGES_INLINE_VARIABLE(adl_insert_detail::insert_fn, insert)
290 
291  namespace actions
292  {
293  using ranges::insert;
294  }
295 } // namespace ranges
296 
297 #include <range/v3/detail/epilogue.hpp>
298 
299 #endif
RANGES_INLINE_VARIABLE(detail::to_container_fn< detail::from_range< std::vector >>, to_vector) template< template< typename... > class ContT > auto to(RANGES_HIDDEN_DETAIL(detail
For initializing a container of the specified type with the elements of an Range.
Definition: conversion.hpp:399
std::integral_constant< bool, B > bool_
An integral constant wrapper for bool.
Definition: meta.hpp:168
meta::size_t< L::size()> size
An integral constant wrapper that is the size of the meta::list L.
Definition: meta.hpp:1696
Definition: insert.hpp:203