diff --git a/headers/flat.hpp/detail/eq_compare.hpp b/headers/flat.hpp/detail/eq_compare.hpp new file mode 100644 index 0000000..7498a41 --- /dev/null +++ b/headers/flat.hpp/detail/eq_compare.hpp @@ -0,0 +1,25 @@ +/******************************************************************************* + * This file is part of the "https://github.com/blackmatov/flat.hpp" + * For conditions of distribution and use, see copyright notice in LICENSE.md + * Copyright (C) 2019, by Matvey Cherevko (blackmatov@gmail.com) + ******************************************************************************/ + +#pragma once + +namespace flat_hpp::detail +{ + template < typename Compare > + class eq_compare : public Compare { + public: + eq_compare() = default; + + eq_compare(const Compare& compare) + : Compare(compare) {} + + template < typename L, typename R > + bool operator()(const L& l, const R& r) const { + return !Compare::operator()(l, r) + && !Compare::operator()(r, l); + } + }; +} diff --git a/headers/flat.hpp/flat_map.hpp b/headers/flat.hpp/flat_map.hpp index fef0b96..0022533 100644 --- a/headers/flat.hpp/flat_map.hpp +++ b/headers/flat.hpp/flat_map.hpp @@ -15,6 +15,7 @@ #include #include +#include "detail/eq_compare.hpp" #include "detail/pair_compare.hpp" #include "detail/is_transparent.hpp" @@ -319,9 +320,13 @@ namespace flat_hpp template < typename InputIter > void insert(InputIter first, InputIter last) { - while ( first != last ) { - insert(*first++); - } + const auto mid_iter = data_.insert(data_.end(), first, last); + std::sort(mid_iter, data_.end(), value_comp()); + std::inplace_merge(data_.begin(), mid_iter, data_.end()); + data_.erase( + std::unique(data_.begin(), data_.end(), + detail::eq_compare(value_comp())), + data_.end()); } void insert(std::initializer_list ilist) { diff --git a/headers/flat.hpp/flat_multimap.hpp b/headers/flat.hpp/flat_multimap.hpp index 2977061..77e0549 100644 --- a/headers/flat.hpp/flat_multimap.hpp +++ b/headers/flat.hpp/flat_multimap.hpp @@ -15,6 +15,7 @@ #include #include +#include "detail/eq_compare.hpp" #include "detail/pair_compare.hpp" #include "detail/is_transparent.hpp" @@ -315,9 +316,9 @@ namespace flat_hpp template < typename InputIter > void insert(InputIter first, InputIter last) { - while ( first != last ) { - insert(*first++); - } + const auto mid_iter = data_.insert(data_.end(), first, last); + std::sort(mid_iter, data_.end(), value_comp()); + std::inplace_merge(data_.begin(), mid_iter, data_.end()); } void insert(std::initializer_list ilist) { diff --git a/headers/flat.hpp/flat_multiset.hpp b/headers/flat.hpp/flat_multiset.hpp index 52f2531..577b9d0 100644 --- a/headers/flat.hpp/flat_multiset.hpp +++ b/headers/flat.hpp/flat_multiset.hpp @@ -15,6 +15,7 @@ #include #include +#include "detail/eq_compare.hpp" #include "detail/is_transparent.hpp" namespace flat_hpp @@ -242,9 +243,9 @@ namespace flat_hpp template < typename InputIter > void insert(InputIter first, InputIter last) { - while ( first != last ) { - insert(*first++); - } + const auto mid_iter = data_.insert(data_.end(), first, last); + std::sort(mid_iter, data_.end(), value_comp()); + std::inplace_merge(data_.begin(), mid_iter, data_.end()); } void insert(std::initializer_list ilist) { diff --git a/headers/flat.hpp/flat_set.hpp b/headers/flat.hpp/flat_set.hpp index aacd2e9..7d0f27c 100644 --- a/headers/flat.hpp/flat_set.hpp +++ b/headers/flat.hpp/flat_set.hpp @@ -15,6 +15,7 @@ #include #include +#include "detail/eq_compare.hpp" #include "detail/is_transparent.hpp" namespace flat_hpp @@ -246,9 +247,13 @@ namespace flat_hpp template < typename InputIter > void insert(InputIter first, InputIter last) { - while ( first != last ) { - insert(*first++); - } + const auto mid_iter = data_.insert(data_.end(), first, last); + std::sort(mid_iter, data_.end(), value_comp()); + std::inplace_merge(data_.begin(), mid_iter, data_.end()); + data_.erase( + std::unique(data_.begin(), data_.end(), + detail::eq_compare(value_comp())), + data_.end()); } void insert(std::initializer_list ilist) { diff --git a/untests/flat_map_tests.cpp b/untests/flat_map_tests.cpp index b0c2c6c..72772c4 100644 --- a/untests/flat_map_tests.cpp +++ b/untests/flat_map_tests.cpp @@ -342,6 +342,14 @@ TEST_CASE("flat_map") { REQUIRE(i6 == s0.end() - 1); REQUIRE(s0 == map_t{{0,21},{1,42},{2,42},{3,84},{4,84},{5,100500},{6,100500}}); } + + { + map_t s0; + s0.insert({{6,2},{4,6},{2,4},{4,2}}); + REQUIRE(s0 == map_t{{2,4},{4,6},{6,2}}); + s0.insert({{9,3},{7,5},{3,9},{5,3},{5,3}}); + REQUIRE(s0 == map_t{{2,4},{3,9},{4,6},{5,3},{6,2},{7,5},{9,3}}); + } } SECTION("erasers") { using map_t = flat_map; diff --git a/untests/flat_multimap_tests.cpp b/untests/flat_multimap_tests.cpp index d7f9dbe..6ba52b7 100644 --- a/untests/flat_multimap_tests.cpp +++ b/untests/flat_multimap_tests.cpp @@ -342,6 +342,14 @@ TEST_CASE("flat_multimap") { REQUIRE(i6 == s0.end() - 1); REQUIRE(s0 == map_t{{0,21},{1,42},{1,21},{2,42},{3,84},{4,84},{5,100500},{6,100500}}); } + + { + map_t s0; + s0.insert({{6,2},{4,6},{2,4},{4,2}}); + REQUIRE(s0 == map_t{{2,4},{4,6},{4,2},{6,2}}); + s0.insert({{9,3},{7,5},{3,9},{5,3},{5,3}}); + REQUIRE(s0 == map_t{{2,4},{3,9},{4,6},{4,2},{5,3},{5,3},{6,2},{7,5},{9,3}}); + } } SECTION("erasers") { using map_t = flat_multimap; diff --git a/untests/flat_multiset_tests.cpp b/untests/flat_multiset_tests.cpp index 8864239..bee3325 100644 --- a/untests/flat_multiset_tests.cpp +++ b/untests/flat_multiset_tests.cpp @@ -318,6 +318,14 @@ TEST_CASE("flat_multiset") { s0.emplace_hint(s0.cend(), 6); // 1,2,3,3,4,5,6 REQUIRE(s0 == set_t{1,2,3,3,4,5,6}); } + + { + set_t s0; + s0.insert({6,4,2,4}); + REQUIRE(s0 == set_t{2,4,4,6}); + s0.insert({9,7,3,5,5}); + REQUIRE(s0 == set_t{2,3,4,4,5,5,6,7,9}); + } } SECTION("erasers") { using set_t = flat_multiset; diff --git a/untests/flat_set_tests.cpp b/untests/flat_set_tests.cpp index 91c59f1..ff1f939 100644 --- a/untests/flat_set_tests.cpp +++ b/untests/flat_set_tests.cpp @@ -318,6 +318,14 @@ TEST_CASE("flat_set") { s0.emplace_hint(s0.cend(), 6); REQUIRE(s0 == set_t{1,2,3,4,5,6}); } + + { + set_t s0; + s0.insert({6,4,2,4}); + REQUIRE(s0 == set_t{2,4,6}); + s0.insert({9,7,3,5,5}); + REQUIRE(s0 == set_t{2,3,4,5,6,7,9}); + } } SECTION("erasers") { using set_t = flat_set;