File indexing completed on 2025-01-18 10:09:42
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef RANGES_V3_ACTION_INSERT_HPP
0015 #define RANGES_V3_ACTION_INSERT_HPP
0016
0017 #include <initializer_list>
0018 #include <utility>
0019
0020 #include <range/v3/range_fwd.hpp>
0021
0022 #include <range/v3/action/concepts.hpp>
0023 #include <range/v3/algorithm/max.hpp>
0024 #include <range/v3/iterator/common_iterator.hpp>
0025 #include <range/v3/range/traits.hpp>
0026 #include <range/v3/utility/static_const.hpp>
0027
0028 #include <range/v3/detail/prologue.hpp>
0029
0030 namespace ranges
0031 {
0032
0033 namespace adl_insert_detail
0034 {
0035 template<typename Cont, typename... Args>
0036 using insert_result_t = decltype(
0037 unwrap_reference(std::declval<Cont>()).insert(std::declval<Args>()...));
0038
0039 template(typename Cont, typename T)(
0040 requires lvalue_container_like<Cont> AND
0041 (!range<T> && constructible_from<range_value_t<Cont>, T>))
0042 insert_result_t<Cont &, T> insert(Cont && cont, T && t)
0043 {
0044 return unwrap_reference(cont).insert(static_cast<T &&>(t));
0045 }
0046
0047 template(typename Cont, typename I, typename S)(
0048 requires lvalue_container_like<Cont> AND sentinel_for<S, I> AND (!range<S>))
0049 insert_result_t<Cont &, detail::cpp17_iterator_t<I, S>,
0050 detail::cpp17_iterator_t<I, S>>
0051 insert(Cont && cont, I i, S j)
0052 {
0053 return unwrap_reference(cont).insert(detail::cpp17_iterator_t<I, S>{i},
0054 detail::cpp17_iterator_t<I, S>{j});
0055 }
0056
0057 template(typename Cont, typename Rng)(
0058 requires lvalue_container_like<Cont> AND range<Rng>)
0059 insert_result_t<Cont &, detail::range_cpp17_iterator_t<Rng>,
0060 detail::range_cpp17_iterator_t<Rng>>
0061 insert(Cont && cont, Rng && rng)
0062 {
0063 return unwrap_reference(cont).insert(
0064 detail::range_cpp17_iterator_t<Rng>{ranges::begin(rng)},
0065 detail::range_cpp17_iterator_t<Rng>{ranges::end(rng)});
0066 }
0067
0068 template(typename Cont, typename I, typename T)(
0069 requires lvalue_container_like<Cont> AND input_iterator<I> AND
0070 (!range<T> && constructible_from<range_value_t<Cont>, T>))
0071 insert_result_t<Cont &, I, T> insert(Cont && cont, I p, T && t)
0072 {
0073 return unwrap_reference(cont).insert(p, static_cast<T &&>(t));
0074 }
0075
0076 template(typename Cont, typename I, typename N, typename T)(
0077 requires lvalue_container_like<Cont> AND input_iterator<I> AND
0078 integral<N> AND constructible_from<range_value_t<Cont>, T>)
0079 insert_result_t<Cont &, I, N, T> insert(Cont && cont, I p, N n, T && t)
0080 {
0081 return unwrap_reference(cont).insert(p, n, static_cast<T &&>(t));
0082 }
0083
0084
0085 namespace detail
0086 {
0087 using ranges::detail::cpp17_iterator_t;
0088 using ranges::detail::range_cpp17_iterator_t;
0089
0090 template(typename Cont, typename P)(
0091 requires container<Cont> AND input_iterator<P> AND
0092 random_access_reservable<Cont>)
0093 iterator_t<Cont> insert_reserve_helper(
0094 Cont & cont, P const p, range_size_t<Cont> const delta)
0095 {
0096 auto const old_size = ranges::size(cont);
0097 auto const max_size = cont.max_size();
0098 RANGES_EXPECT(delta <= max_size - old_size);
0099 auto const new_size = old_size + delta;
0100 auto const old_capacity = cont.capacity();
0101 auto const index = p - ranges::begin(cont);
0102 if(old_capacity < new_size)
0103 {
0104 auto const new_capacity =
0105 (old_capacity <= max_size / 3 * 2)
0106 ? ranges::max(old_capacity + old_capacity / 2, new_size)
0107 : max_size;
0108 cont.reserve(new_capacity);
0109 }
0110 return ranges::begin(cont) + index;
0111 }
0112
0113 template(typename Cont, typename P, typename I, typename S)(
0114 requires sentinel_for<S, I> AND (!range<S>))
0115 auto insert_impl(Cont && cont, P p, I i, S j, std::false_type)
0116 -> decltype(unwrap_reference(cont).insert(
0117 p, cpp17_iterator_t<I, S>{i}, cpp17_iterator_t<I, S>{j}))
0118 {
0119 using C = cpp17_iterator_t<I, S>;
0120 return unwrap_reference(cont).insert(p, C{i}, C{j});
0121 }
0122
0123 template(typename Cont, typename P, typename I, typename S)(
0124 requires sized_sentinel_for<S, I> AND random_access_reservable<Cont> AND
0125 (!range<S>))
0126 auto insert_impl(Cont && cont_, P p, I i, S j, std::true_type)
0127 -> decltype(unwrap_reference(cont_).insert(
0128 ranges::begin(unwrap_reference(cont_)), cpp17_iterator_t<I, S>{i},
0129 cpp17_iterator_t<I, S>{j}))
0130 {
0131 using C = cpp17_iterator_t<I, S>;
0132 auto && cont = unwrap_reference(cont_);
0133 auto const delta = static_cast<range_size_t<Cont>>(j - i);
0134 auto pos = insert_reserve_helper(cont, std::move(p), delta);
0135 return cont.insert(pos, C{std::move(i)}, C{std::move(j)});
0136 }
0137
0138 template(typename Cont, typename I, typename Rng)(
0139 requires range<Rng>)
0140 auto insert_impl(Cont && cont, I p, Rng && rng, std::false_type)
0141 -> decltype(unwrap_reference(cont).insert(
0142 p, range_cpp17_iterator_t<Rng>{ranges::begin(rng)},
0143 range_cpp17_iterator_t<Rng>{ranges::end(rng)}))
0144 {
0145 using C = range_cpp17_iterator_t<Rng>;
0146 return unwrap_reference(cont).insert(
0147 p, C{ranges::begin(rng)}, C{ranges::end(rng)});
0148 }
0149
0150 template(typename Cont, typename I, typename Rng)(
0151 requires random_access_reservable<Cont> AND sized_range<Rng>)
0152 auto insert_impl(Cont && cont_, I p, Rng && rng, std::true_type)
0153 -> decltype(unwrap_reference(cont_).insert(
0154 begin(unwrap_reference(cont_)),
0155 range_cpp17_iterator_t<Rng>{ranges::begin(rng)},
0156 range_cpp17_iterator_t<Rng>{ranges::end(rng)}))
0157 {
0158 using C = range_cpp17_iterator_t<Rng>;
0159 auto && cont = unwrap_reference(cont_);
0160 auto const delta = static_cast<range_size_t<Cont>>(ranges::size(rng));
0161 auto pos = insert_reserve_helper(cont, std::move(p), delta);
0162 return cont.insert(pos, C{ranges::begin(rng)}, C{ranges::end(rng)});
0163 }
0164 }
0165
0166
0167 template(typename Cont, typename P, typename I, typename S)(
0168 requires lvalue_container_like<Cont> AND input_iterator<P> AND
0169 sentinel_for<S, I> AND
0170 (!range<S>))
0171 auto insert(Cont && cont, P p, I i, S j)
0172 -> decltype(detail::insert_impl(
0173 static_cast<Cont &&>(cont),
0174 static_cast<P &&>(p),
0175 static_cast<I &&>(i),
0176 static_cast<S &&>(j),
0177 meta::bool_<random_access_reservable<Cont> &&
0178 sized_sentinel_for<S, I>>{}))
0179 {
0180 return detail::insert_impl(static_cast<Cont &&>(cont),
0181 static_cast<P &&>(p),
0182 static_cast<I &&>(i),
0183 static_cast<S &&>(j),
0184 meta::bool_<random_access_reservable<Cont> &&
0185 sized_sentinel_for<S, I>>{});
0186 }
0187
0188 template(typename Cont, typename I, typename Rng)(
0189 requires lvalue_container_like<Cont> AND input_iterator<I> AND range<Rng>)
0190 auto insert(Cont && cont, I p, Rng && rng)
0191 -> decltype(detail::insert_impl(
0192 static_cast<Cont &&>(cont), std::move(p), static_cast<Rng &&>(rng),
0193 meta::bool_<random_access_reservable<Cont> && sized_range<Rng>>{}))
0194 {
0195 return detail::insert_impl(static_cast<Cont &&>(cont),
0196 std::move(p),
0197 static_cast<Rng &&>(rng),
0198 meta::bool_<random_access_reservable<Cont> &&
0199 sized_range<Rng>>{});
0200 }
0201
0202 struct insert_fn
0203 {
0204 template<typename Rng, typename... Args>
0205 using insert_result_t =
0206 decltype(insert(std::declval<Rng>(), std::declval<Args>()...));
0207
0208 template(typename Rng, typename T)(
0209 requires range<Rng> AND
0210 (!range<T>) AND constructible_from<range_value_t<Rng>, T>)
0211 insert_result_t<Rng, T> operator()(Rng && rng, T && t) const
0212 {
0213 return insert(static_cast<Rng &&>(rng), static_cast<T &&>(t));
0214 }
0215
0216 template(typename Rng, typename Rng2)(
0217 requires range<Rng> AND range<Rng2>)
0218 insert_result_t<Rng, Rng2> operator()(Rng && rng, Rng2 && rng2) const
0219 {
0220 static_assert(!is_infinite<Rng>::value,
0221 "Attempting to insert an infinite range into a container");
0222 return insert(static_cast<Rng &&>(rng), static_cast<Rng2 &&>(rng2));
0223 }
0224
0225 template(typename Rng, typename T)(
0226 requires range<Rng>)
0227 insert_result_t<Rng, std::initializer_list<T> &>
0228 operator()(Rng && rng, std::initializer_list<T> rng2) const
0229 {
0230 return insert(static_cast<Rng &&>(rng), rng2);
0231 }
0232
0233 template(typename Rng, typename I, typename S)(
0234 requires range<Rng> AND sentinel_for<S, I> AND (!range<S>))
0235 insert_result_t<Rng, I, S> operator()(Rng && rng, I i, S j) const
0236 {
0237 return insert(static_cast<Rng &&>(rng), std::move(i), std::move(j));
0238 }
0239
0240 template(typename Rng, typename I, typename T)(
0241 requires range<Rng> AND input_iterator<I> AND
0242 (!range<T>) AND constructible_from<range_value_t<Rng>, T>)
0243 insert_result_t<Rng, I, T> operator()(Rng && rng, I p, T && t) const
0244 {
0245 return insert(
0246 static_cast<Rng &&>(rng), std::move(p), static_cast<T &&>(t));
0247 }
0248
0249 template(typename Rng, typename I, typename Rng2)(
0250 requires range<Rng> AND input_iterator<I> AND range<Rng2>)
0251 insert_result_t<Rng, I, Rng2> operator()(Rng && rng, I p, Rng2 && rng2) const
0252 {
0253 static_assert(!is_infinite<Rng>::value,
0254 "Attempting to insert an infinite range into a container");
0255 return insert(
0256 static_cast<Rng &&>(rng), std::move(p), static_cast<Rng2 &&>(rng2));
0257 }
0258
0259 template(typename Rng, typename I, typename T)(
0260 requires range<Rng> AND input_iterator<I>)
0261 insert_result_t<Rng, I, std::initializer_list<T> &>
0262 operator()(Rng && rng, I p, std::initializer_list<T> rng2) const
0263 {
0264 return insert(static_cast<Rng &&>(rng), std::move(p), rng2);
0265 }
0266
0267 template(typename Rng, typename I, typename N, typename T)(
0268 requires range<Rng> AND input_iterator<I> AND integral<N> AND
0269 (!range<T>) AND constructible_from<range_value_t<Rng>, T>)
0270 insert_result_t<Rng, I, N, T> operator()(Rng && rng, I p, N n, T && t) const
0271 {
0272 return insert(
0273 static_cast<Rng &&>(rng), std::move(p), n, static_cast<T &&>(t));
0274 }
0275
0276 template(typename Rng, typename P, typename I, typename S)(
0277 requires range<Rng> AND input_iterator<P> AND sentinel_for<S, I> AND
0278 (!range<S>))
0279 insert_result_t<Rng, P, I, S> operator()(Rng && rng, P p, I i, S j) const
0280 {
0281 return insert(
0282 static_cast<Rng &&>(rng), std::move(p), std::move(i), std::move(j));
0283 }
0284 };
0285 }
0286
0287
0288
0289 RANGES_INLINE_VARIABLE(adl_insert_detail::insert_fn, insert)
0290
0291 namespace actions
0292 {
0293 using ranges::insert;
0294 }
0295 }
0296
0297 #include <range/v3/detail/epilogue.hpp>
0298
0299 #endif