/// \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 #include namespace ranges { /// \cond namespace adl_insert_detail { template using insert_result_t = decltype( unwrap_reference(std::declval()).insert(std::declval()...)); template(typename Cont, typename T)( requires lvalue_container_like AND (!range && constructible_from, T>)) // insert_result_t insert(Cont && cont, T && t) { return unwrap_reference(cont).insert(static_cast(t)); } template(typename Cont, typename I, typename S)( requires lvalue_container_like AND sentinel_for AND (!range)) insert_result_t, detail::cpp17_iterator_t> insert(Cont && cont, I i, S j) { return unwrap_reference(cont).insert(detail::cpp17_iterator_t{i}, detail::cpp17_iterator_t{j}); } template(typename Cont, typename Rng)( requires lvalue_container_like AND range) insert_result_t, detail::range_cpp17_iterator_t> insert(Cont && cont, Rng && rng) { return unwrap_reference(cont).insert( detail::range_cpp17_iterator_t{ranges::begin(rng)}, detail::range_cpp17_iterator_t{ranges::end(rng)}); } template(typename Cont, typename I, typename T)( requires lvalue_container_like AND input_iterator AND (!range && constructible_from, T>)) // insert_result_t insert(Cont && cont, I p, T && t) { return unwrap_reference(cont).insert(p, static_cast(t)); } template(typename Cont, typename I, typename N, typename T)( requires lvalue_container_like AND input_iterator AND integral AND constructible_from, T>) insert_result_t insert(Cont && cont, I p, N n, T && 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(typename Cont, typename P)( requires container AND input_iterator

AND random_access_reservable) iterator_t insert_reserve_helper( Cont & cont, P const p, range_size_t const delta) { 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(typename Cont, typename P, typename I, typename S)( requires sentinel_for AND (!range)) // auto insert_impl(Cont && cont, P p, I i, S j, std::false_type) -> decltype(unwrap_reference(cont).insert( p, cpp17_iterator_t{i}, cpp17_iterator_t{j})) { using C = cpp17_iterator_t; return unwrap_reference(cont).insert(p, C{i}, C{j}); } template(typename Cont, typename P, typename I, typename S)( requires sized_sentinel_for AND random_access_reservable AND (!range)) // auto insert_impl(Cont && cont_, P p, I i, S j, std::true_type) -> decltype(unwrap_reference(cont_).insert( ranges::begin(unwrap_reference(cont_)), cpp17_iterator_t{i}, cpp17_iterator_t{j})) { 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(typename Cont, typename I, typename Rng)( requires range) auto insert_impl(Cont && cont, I p, Rng && rng, std::false_type) -> decltype(unwrap_reference(cont).insert( p, range_cpp17_iterator_t{ranges::begin(rng)}, range_cpp17_iterator_t{ranges::end(rng)})) { using C = range_cpp17_iterator_t; return unwrap_reference(cont).insert( p, C{ranges::begin(rng)}, C{ranges::end(rng)}); } template(typename Cont, typename I, typename Rng)( requires random_access_reservable AND sized_range) auto insert_impl(Cont && cont_, I p, Rng && rng, std::true_type) -> decltype(unwrap_reference(cont_).insert( begin(unwrap_reference(cont_)), range_cpp17_iterator_t{ranges::begin(rng)}, range_cpp17_iterator_t{ranges::end(rng)})) { 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(typename Cont, typename P, typename I, typename S)( requires lvalue_container_like AND input_iterator

AND sentinel_for AND (!range)) // auto insert(Cont && cont, P p, I i, S j) // -> decltype(detail::insert_impl( static_cast(cont), static_cast

(p), static_cast(i), static_cast(j), meta::bool_ && // sized_sentinel_for>{})) { return detail::insert_impl(static_cast(cont), static_cast

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

AND sentinel_for AND (!range)) // insert_result_t operator()(Rng && rng, P p, I i, S j) const { 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 #include #endif