/// \file // Range v3 library // // Copyright Eric Niebler 2013-present // // Use, modification and distribution is subject to the // Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) // // Project home: https://github.com/ericniebler/range-v3 // #ifndef RANGES_V3_ACTION_INSERT_HPP #define RANGES_V3_ACTION_INSERT_HPP #include #include #include #include #include #include #include #include namespace ranges { /// \cond namespace adl_insert_detail { template using insert_result_t = decltype( unwrap_reference(std::declval()).insert(std::declval()...)); template auto insert(Cont && cont, T && t) -> CPP_ret(insert_result_t)( // requires lvalue_container_like && (!range && constructible_from, T>)) { return unwrap_reference(cont).insert(static_cast(t)); } template auto insert(Cont && cont, I i, S j) -> CPP_ret(insert_result_t, detail::cpp17_iterator_t>)( // requires lvalue_container_like && sentinel_for && (!range)) { return unwrap_reference(cont).insert(detail::cpp17_iterator_t{i}, detail::cpp17_iterator_t{j}); } template auto insert(Cont && cont, Rng && rng) -> CPP_ret(insert_result_t, detail::range_cpp17_iterator_t>)( // requires lvalue_container_like && range) { return unwrap_reference(cont).insert( detail::range_cpp17_iterator_t{ranges::begin(rng)}, detail::range_cpp17_iterator_t{ranges::end(rng)}); } template auto insert(Cont && cont, I p, T && t) -> CPP_ret(insert_result_t)( // requires lvalue_container_like && input_iterator && (!range && constructible_from, T>)) { return unwrap_reference(cont).insert(p, static_cast(t)); } template auto insert(Cont && cont, I p, N n, T && t) -> CPP_ret(insert_result_t)( // requires lvalue_container_like && input_iterator && integral && constructible_from, T>) { return unwrap_reference(cont).insert(p, n, static_cast(t)); } /// \cond namespace detail { using ranges::detail::cpp17_iterator_t; using ranges::detail::range_cpp17_iterator_t; template auto insert_reserve_helper(Cont & cont, P const p, range_size_t const delta) -> CPP_ret(iterator_t)( // requires container && input_iterator

&& random_access_reservable) { auto const old_size = ranges::size(cont); auto const max_size = cont.max_size(); RANGES_EXPECT(delta <= max_size - old_size); auto const new_size = old_size + delta; auto const old_capacity = cont.capacity(); auto const index = p - ranges::begin(cont); if(old_capacity < new_size) { auto const new_capacity = (old_capacity <= max_size / 3 * 2) ? ranges::max(old_capacity + old_capacity / 2, new_size) : max_size; cont.reserve(new_capacity); } return ranges::begin(cont) + index; } template auto insert_impl(Cont && cont, P p, I i, S j, std::false_type) -> CPP_ret(decltype(unwrap_reference(cont).insert( p, cpp17_iterator_t{i}, cpp17_iterator_t{j})))( // requires sentinel_for && (!range)) { using C = cpp17_iterator_t; return unwrap_reference(cont).insert(p, C{i}, C{j}); } template auto insert_impl(Cont && cont_, P p, I i, S j, std::true_type) -> CPP_ret(decltype(unwrap_reference(cont_).insert( ranges::begin(unwrap_reference(cont_)), cpp17_iterator_t{i}, cpp17_iterator_t{j})))( // requires sized_sentinel_for && random_access_reservable && (!range)) { using C = cpp17_iterator_t; auto && cont = unwrap_reference(cont_); auto const delta = static_cast>(j - i); auto pos = insert_reserve_helper(cont, std::move(p), delta); return cont.insert(pos, C{std::move(i)}, C{std::move(j)}); } template auto insert_impl(Cont && cont, I p, Rng && rng, std::false_type) -> CPP_ret(decltype(unwrap_reference(cont).insert( p, range_cpp17_iterator_t{ranges::begin(rng)}, range_cpp17_iterator_t{ranges::end(rng)})))( // requires range) { using C = range_cpp17_iterator_t; return unwrap_reference(cont).insert( p, C{ranges::begin(rng)}, C{ranges::end(rng)}); } template auto insert_impl(Cont && cont_, I p, Rng && rng, std::true_type) -> CPP_ret(decltype(unwrap_reference(cont_).insert( begin(unwrap_reference(cont_)), range_cpp17_iterator_t{ranges::begin(rng)}, range_cpp17_iterator_t{ranges::end(rng)})))( // requires random_access_reservable && sized_range) { using C = range_cpp17_iterator_t; auto && cont = unwrap_reference(cont_); auto const delta = static_cast>(ranges::size(rng)); auto pos = insert_reserve_helper(cont, std::move(p), delta); return cont.insert(pos, C{ranges::begin(rng)}, C{ranges::end(rng)}); } } // namespace detail /// \endcond template auto insert(Cont && cont, P p, I i, S j) -> CPP_ret(decltype(detail::insert_impl( static_cast(cont), std::move(p), std::move(i), std::move(j), meta::bool_ && sized_sentinel_for>{})))( // requires lvalue_container_like && input_iterator

&& sentinel_for && (!range)) { return detail::insert_impl(static_cast(cont), std::move(p), std::move(i), std::move(j), meta::bool_ < random_access_reservable && sized_sentinel_for> {}); } template auto insert(Cont && cont, I p, Rng && rng) -> CPP_ret(decltype(detail::insert_impl( static_cast(cont), std::move(p), static_cast(rng), meta::bool_ && sized_range>{})))( // requires lvalue_container_like && input_iterator && range) { return detail::insert_impl(static_cast(cont), std::move(p), static_cast(rng), meta::bool_ < random_access_reservable && sized_range> {}); } struct insert_fn { template using insert_result_t = decltype(insert(std::declval(), std::declval()...)); template auto operator()(Rng && rng, T && t) const -> CPP_ret(insert_result_t)( // requires range && (!range)&&constructible_from, T>) { return insert(static_cast(rng), static_cast(t)); } template auto operator()(Rng && rng, Rng2 && rng2) const -> CPP_ret(insert_result_t)( // requires range && range) { static_assert(!is_infinite::value, "Attempting to insert an infinite range into a container"); return insert(static_cast(rng), static_cast(rng2)); } template auto operator()(Rng && rng, std::initializer_list rng2) const -> CPP_ret(insert_result_t &>)( // requires range) { return insert(static_cast(rng), rng2); } template auto operator()(Rng && rng, I i, S j) const -> CPP_ret(insert_result_t)( // requires range && sentinel_for && (!range)) { return insert(static_cast(rng), std::move(i), std::move(j)); } template auto operator()(Rng && rng, I p, T && t) const -> CPP_ret(insert_result_t)( // requires range && input_iterator && (!range)&&constructible_from, T>) { return insert( static_cast(rng), std::move(p), static_cast(t)); } template auto operator()(Rng && rng, I p, Rng2 && rng2) const -> CPP_ret(insert_result_t)( // requires range && input_iterator && range) { static_assert(!is_infinite::value, "Attempting to insert an infinite range into a container"); return insert( static_cast(rng), std::move(p), static_cast(rng2)); } template auto operator()(Rng && rng, I p, std::initializer_list rng2) const -> CPP_ret(insert_result_t &>)( // requires range && input_iterator) { return insert(static_cast(rng), std::move(p), rng2); } template auto operator()(Rng && rng, I p, N n, T && t) const -> CPP_ret(insert_result_t)( // requires range && input_iterator && integral && (!range)&&constructible_from, T>) { return insert( static_cast(rng), std::move(p), n, static_cast(t)); } template auto operator()(Rng && rng, P p, I i, S j) const -> CPP_ret(insert_result_t)( // requires range && input_iterator

&& sentinel_for && (!range)) { return insert( static_cast(rng), std::move(p), std::move(i), std::move(j)); } }; } // namespace adl_insert_detail /// \endcond /// \ingroup group-actions RANGES_INLINE_VARIABLE(adl_insert_detail::insert_fn, insert) namespace actions { using ranges::insert; } } // namespace ranges #endif