From d906bf57e08273614674d4d4ed7ced56032479f8 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Fri, 31 May 2019 05:29:54 +0700 Subject: [PATCH 1/7] remove O(n^2) complexity from range and initialiser list inserts #7 --- headers/flat.hpp/detail/eq_compare.hpp | 25 +++++++++++++++++++++++++ headers/flat.hpp/flat_map.hpp | 11 ++++++++--- headers/flat.hpp/flat_multimap.hpp | 7 ++++--- headers/flat.hpp/flat_multiset.hpp | 7 ++++--- headers/flat.hpp/flat_set.hpp | 11 ++++++++--- untests/flat_map_tests.cpp | 8 ++++++++ untests/flat_multimap_tests.cpp | 8 ++++++++ untests/flat_multiset_tests.cpp | 8 ++++++++ untests/flat_set_tests.cpp | 8 ++++++++ 9 files changed, 81 insertions(+), 12 deletions(-) create mode 100644 headers/flat.hpp/detail/eq_compare.hpp 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; From 5b67609aabf9bd18060789871c3e9eb9c8bbe923 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Fri, 31 May 2019 06:29:28 +0700 Subject: [PATCH 2/7] add common fwd header --- headers/flat.hpp/flat_fwd.hpp | 44 ++++++++++++++++++++++++++++++ headers/flat.hpp/flat_map.hpp | 17 ++---------- headers/flat.hpp/flat_multimap.hpp | 17 ++---------- headers/flat.hpp/flat_multiset.hpp | 16 ++--------- headers/flat.hpp/flat_set.hpp | 16 ++--------- 5 files changed, 56 insertions(+), 54 deletions(-) create mode 100644 headers/flat.hpp/flat_fwd.hpp diff --git a/headers/flat.hpp/flat_fwd.hpp b/headers/flat.hpp/flat_fwd.hpp new file mode 100644 index 0000000..869022d --- /dev/null +++ b/headers/flat.hpp/flat_fwd.hpp @@ -0,0 +1,44 @@ +/******************************************************************************* + * 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 + +#include +#include +#include +#include +#include +#include +#include + +#include "detail/eq_compare.hpp" +#include "detail/pair_compare.hpp" +#include "detail/is_transparent.hpp" + +namespace flat_hpp +{ + template < typename Key + , typename Compare = std::less + , typename Container = std::vector > + class flat_set; + + template < typename Key + , typename Compare = std::less + , typename Container = std::vector > + class flat_multiset; + + template < typename Key + , typename Value + , typename Compare = std::less + , typename Container = std::vector> > + class flat_map; + + template < typename Key + , typename Value + , typename Compare = std::less + , typename Container = std::vector> > + class flat_multimap; +} diff --git a/headers/flat.hpp/flat_map.hpp b/headers/flat.hpp/flat_map.hpp index 0022533..c1a3679 100644 --- a/headers/flat.hpp/flat_map.hpp +++ b/headers/flat.hpp/flat_map.hpp @@ -6,25 +6,14 @@ #pragma once -#include -#include -#include -#include -#include -#include -#include -#include - -#include "detail/eq_compare.hpp" -#include "detail/pair_compare.hpp" -#include "detail/is_transparent.hpp" +#include "flat_fwd.hpp" namespace flat_hpp { template < typename Key , typename Value - , typename Compare = std::less - , typename Container = std::vector> > + , typename Compare + , typename Container > class flat_map : private detail::pair_compare< typename Container::value_type, diff --git a/headers/flat.hpp/flat_multimap.hpp b/headers/flat.hpp/flat_multimap.hpp index 77e0549..65bbc6b 100644 --- a/headers/flat.hpp/flat_multimap.hpp +++ b/headers/flat.hpp/flat_multimap.hpp @@ -6,25 +6,14 @@ #pragma once -#include -#include -#include -#include -#include -#include -#include -#include - -#include "detail/eq_compare.hpp" -#include "detail/pair_compare.hpp" -#include "detail/is_transparent.hpp" +#include "flat_fwd.hpp" namespace flat_hpp { template < typename Key , typename Value - , typename Compare = std::less - , typename Container = std::vector> > + , typename Compare + , typename Container > class flat_multimap : private detail::pair_compare< typename Container::value_type, diff --git a/headers/flat.hpp/flat_multiset.hpp b/headers/flat.hpp/flat_multiset.hpp index 577b9d0..2ecc8df 100644 --- a/headers/flat.hpp/flat_multiset.hpp +++ b/headers/flat.hpp/flat_multiset.hpp @@ -6,23 +6,13 @@ #pragma once -#include -#include -#include -#include -#include -#include -#include -#include - -#include "detail/eq_compare.hpp" -#include "detail/is_transparent.hpp" +#include "flat_fwd.hpp" namespace flat_hpp { template < typename Key - , typename Compare = std::less - , typename Container = std::vector > + , typename Compare + , typename Container > class flat_multiset : private Compare { using base_type = Compare; public: diff --git a/headers/flat.hpp/flat_set.hpp b/headers/flat.hpp/flat_set.hpp index 7d0f27c..132ac9e 100644 --- a/headers/flat.hpp/flat_set.hpp +++ b/headers/flat.hpp/flat_set.hpp @@ -6,23 +6,13 @@ #pragma once -#include -#include -#include -#include -#include -#include -#include -#include - -#include "detail/eq_compare.hpp" -#include "detail/is_transparent.hpp" +#include "flat_fwd.hpp" namespace flat_hpp { template < typename Key - , typename Compare = std::less - , typename Container = std::vector > + , typename Compare + , typename Container > class flat_set : private Compare { using base_type = Compare; public: From 8104ebd598e96533bd0ca89cf3aeb0f7547c1f9c Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Fri, 31 May 2019 07:19:53 +0700 Subject: [PATCH 3/7] add insert sorted ranges optimization #23 --- README.md | 100 ++++++++++++++++++++++++ headers/flat.hpp/detail/is_sorted.hpp | 26 +++++++ headers/flat.hpp/flat_fwd.hpp | 7 ++ headers/flat.hpp/flat_map.hpp | 107 ++++++++++++++++++++++++++ headers/flat.hpp/flat_multimap.hpp | 57 ++++++++++++++ headers/flat.hpp/flat_multiset.hpp | 57 ++++++++++++++ headers/flat.hpp/flat_set.hpp | 107 ++++++++++++++++++++++++++ untests/flat_map_tests.cpp | 10 +++ untests/flat_multimap_tests.cpp | 10 +++ untests/flat_multiset_tests.cpp | 10 +++ untests/flat_set_tests.cpp | 10 +++ 11 files changed, 501 insertions(+) create mode 100644 headers/flat.hpp/detail/is_sorted.hpp diff --git a/README.md b/README.md index 58c2cce..58b3f86 100644 --- a/README.md +++ b/README.md @@ -95,25 +95,53 @@ flat_set(const Compare& c, const Allocator& a); template < typename InputIter > flat_set(InputIter first, InputIter last); +template < typename InputIter > +flat_set(sorted_range_t, InputIter first, InputIter last); +template < typename InputIter > +flat_set(sorted_unique_range_t, InputIter first, InputIter last); template < typename InputIter > flat_set(InputIter first, InputIter last, const Compare& c); +template < typename InputIter > +flat_set(sorted_range_t, InputIter first, InputIter last, const Compare& c); +template < typename InputIter > +flat_set(sorted_unique_range_t, InputIter first, InputIter last, const Compare& c); template < typename InputIter, typename Allocator > flat_set(InputIter first, InputIter last, const Allocator& a); +template < typename InputIter, typename Allocator > +flat_set(sorted_range_t, InputIter first, InputIter last, const Allocator& a); +template < typename InputIter, typename Allocator > +flat_set(sorted_unique_range_t, InputIter first, InputIter last, const Allocator& a); template < typename InputIter, typename Allocator > flat_set(InputIter first, InputIter last, const Compare& c, const Allocator& a); +template < typename InputIter, typename Allocator > +flat_set(sorted_range_t, InputIter first, InputIter last, const Compare& c, const Allocator& a); +template < typename InputIter, typename Allocator > +flat_set(sorted_unique_range_t, InputIter first, InputIter last, const Compare& c, const Allocator& a); flat_set(std::initializer_list ilist); +flat_set(sorted_range_t, std::initializer_list ilist); +flat_set(sorted_unique_range_t, std::initializer_list ilist); flat_set(std::initializer_list ilist, const Compare& c); +flat_set(sorted_range_t, std::initializer_list ilist, const Compare& c); +flat_set(sorted_unique_range_t, std::initializer_list ilist, const Compare& c); template < typename Allocator > flat_set(std::initializer_list ilist, const Allocator& a); +template < typename Allocator > +flat_set(sorted_range_t, std::initializer_list ilist, const Allocator& a); +template < typename Allocator > +flat_set(sorted_unique_range_t, std::initializer_list ilist, const Allocator& a); template < typename Allocator > flat_set(std::initializer_list ilist, const Compare& c, const Allocator& a); +template < typename Allocator > +flat_set(sorted_range_t, std::initializer_list ilist, const Compare& c, const Allocator& a); +template < typename Allocator > +flat_set(sorted_unique_range_t, std::initializer_list ilist, const Compare& c, const Allocator& a); template < typename Allocator > flat_set(flat_set&& other, const Allocator& a); @@ -172,7 +200,11 @@ iterator insert(const_iterator hint, const value_type& value); template < typename InputIter > void insert(InputIter first, InputIter last); +template < typename InputIter > +void insert(sorted_range_t, InputIter first, InputIter last); + void insert(std::initializer_list ilist); +void insert(sorted_range_t, std::initializer_list ilist); template < typename... Args > std::pair emplace(Args&&... args); @@ -329,25 +361,53 @@ flat_map(const Compare& c, const Allocator& a); template < typename InputIter > flat_map(InputIter first, InputIter last); +template < typename InputIter > +flat_map(sorted_range_t, InputIter first, InputIter last); +template < typename InputIter > +flat_map(sorted_unique_range_t, InputIter first, InputIter last); template < typename InputIter > flat_map(InputIter first, InputIter last, const Compare& c); +template < typename InputIter > +flat_map(sorted_range_t, InputIter first, InputIter last, const Compare& c); +template < typename InputIter > +flat_map(sorted_unique_range_t, InputIter first, InputIter last, const Compare& c); template < typename InputIter, typename Allocator > flat_map(InputIter first, InputIter last, const Allocator& a); +template < typename InputIter, typename Allocator > +flat_map(sorted_range_t, InputIter first, InputIter last, const Allocator& a); +template < typename InputIter, typename Allocator > +flat_map(sorted_unique_range_t, InputIter first, InputIter last, const Allocator& a); template < typename InputIter , typename Allocator > flat_map(InputIter first, InputIter last, const Compare& c, const Allocator& a); +template < typename InputIter , typename Allocator > +flat_map(sorted_range_t, InputIter first, InputIter last, const Compare& c, const Allocator& a); +template < typename InputIter , typename Allocator > +flat_map(sorted_unique_range_t, InputIter first, InputIter last, const Compare& c, const Allocator& a); flat_map(std::initializer_list ilist); +flat_map(sorted_range_t, std::initializer_list ilist); +flat_map(sorted_unique_range_t, std::initializer_list ilist); flat_map(std::initializer_list ilist, const Compare& c); +flat_map(sorted_range_t, std::initializer_list ilist, const Compare& c); +flat_map(sorted_unique_range_t, std::initializer_list ilist, const Compare& c); template < typename Allocator > flat_map(std::initializer_list ilist, const Allocator& a); +template < typename Allocator > +flat_map(sorted_range_t, std::initializer_list ilist, const Allocator& a); +template < typename Allocator > +flat_map(sorted_unique_range_t, std::initializer_list ilist, const Allocator& a); template < typename Allocator > flat_map(std::initializer_list ilist, const Compare& c, const Allocator& a); +template < typename Allocator > +flat_map(sorted_range_t, std::initializer_list ilist, const Compare& c, const Allocator& a); +template < typename Allocator > +flat_map(sorted_unique_range_t, std::initializer_list ilist, const Compare& c, const Allocator& a); template < typename Allocator > flat_map(flat_map&& other, const Allocator& a); @@ -419,7 +479,11 @@ iterator insert(const_iterator hint, const value_type& value); template < typename InputIter > void insert(InputIter first, InputIter last); +template < typename InputIter > +void insert(sorted_range_t, InputIter first, InputIter last); + void insert(std::initializer_list ilist); +void insert(sorted_range_t, std::initializer_list ilist); template < typename... Args > std::pair emplace(Args&&... args); @@ -576,25 +640,39 @@ flat_multiset(const Compare& c, const Allocator& a); template < typename InputIter > flat_multiset(InputIter first, InputIter last); +template < typename InputIter > +flat_multiset(sorted_range_t, InputIter first, InputIter last); template < typename InputIter > flat_multiset(InputIter first, InputIter last, const Compare& c); +template < typename InputIter > +flat_multiset(sorted_range_t, InputIter first, InputIter last, const Compare& c); template < typename InputIter, typename Allocator > flat_multiset(InputIter first, InputIter last, const Allocator& a); +template < typename InputIter, typename Allocator > +flat_multiset(sorted_range_t, InputIter first, InputIter last, const Allocator& a); template < typename InputIter, typename Allocator > flat_multiset(InputIter first, InputIter last, const Compare& c, const Allocator& a); +template < typename InputIter, typename Allocator > +flat_multiset(sorted_range_t, InputIter first, InputIter last, const Compare& c, const Allocator& a); flat_multiset(std::initializer_list ilist); +flat_multiset(sorted_range_t, std::initializer_list ilist); flat_multiset(std::initializer_list ilist, const Compare& c); +flat_multiset(sorted_range_t, std::initializer_list ilist, const Compare& c); template < typename Allocator > flat_multiset(std::initializer_list ilist, const Allocator& a); +template < typename Allocator > +flat_multiset(sorted_range_t, std::initializer_list ilist, const Allocator& a); template < typename Allocator > flat_multiset(std::initializer_list ilist, const Compare& c, const Allocator& a); +template < typename Allocator > +flat_multiset(sorted_range_t, std::initializer_list ilist, const Compare& c, const Allocator& a); template < typename Allocator > flat_multiset(flat_multiset&& other, const Allocator& a); @@ -653,7 +731,11 @@ iterator insert(const_iterator hint, const value_type& value); template < typename InputIter > void insert(InputIter first, InputIter last); +template < typename InputIter > +void insert(sorted_range_t, InputIter first, InputIter last); + void insert(std::initializer_list ilist); +void insert(sorted_range_t, std::initializer_list ilist); template < typename... Args > iterator emplace(Args&&... args); @@ -810,25 +892,39 @@ flat_multimap(const Compare& c, const Allocator& a); template < typename InputIter > flat_multimap(InputIter first, InputIter last); +template < typename InputIter > +flat_multimap(sorted_range_t, InputIter first, InputIter last); template < typename InputIter > flat_multimap(InputIter first, InputIter last, const Compare& c); +template < typename InputIter > +flat_multimap(sorted_range_t, InputIter first, InputIter last, const Compare& c); template < typename InputIter, typename Allocator > flat_multimap(InputIter first, InputIter last, const Allocator& a); +template < typename InputIter, typename Allocator > +flat_multimap(sorted_range_t, InputIter first, InputIter last, const Allocator& a); template < typename InputIter , typename Allocator > flat_multimap(InputIter first, InputIter last, const Compare& c, const Allocator& a); +template < typename InputIter , typename Allocator > +flat_multimap(sorted_range_t, InputIter first, InputIter last, const Compare& c, const Allocator& a); flat_multimap(std::initializer_list ilist); +flat_multimap(sorted_range_t, std::initializer_list ilist); flat_multimap(std::initializer_list ilist, const Compare& c); +flat_multimap(sorted_range_t, std::initializer_list ilist, const Compare& c); template < typename Allocator > flat_multimap(std::initializer_list ilist, const Allocator& a); +template < typename Allocator > +flat_multimap(sorted_range_t, std::initializer_list ilist, const Allocator& a); template < typename Allocator > flat_multimap(std::initializer_list ilist, const Compare& c, const Allocator& a); +template < typename Allocator > +flat_multimap(sorted_range_t, std::initializer_list ilist, const Compare& c, const Allocator& a); template < typename Allocator > flat_multimap(flat_multimap&& other, const Allocator& a); @@ -900,7 +996,11 @@ iterator insert(const_iterator hint, const value_type& value); template < typename InputIter > void insert(InputIter first, InputIter last); +template < typename InputIter > +void insert(sorted_range_t, InputIter first, InputIter last); + void insert(std::initializer_list ilist); +void insert(sorted_range_t, std::initializer_list ilist); template < typename... Args > iterator emplace(Args&&... args); diff --git a/headers/flat.hpp/detail/is_sorted.hpp b/headers/flat.hpp/detail/is_sorted.hpp new file mode 100644 index 0000000..7e63a49 --- /dev/null +++ b/headers/flat.hpp/detail/is_sorted.hpp @@ -0,0 +1,26 @@ +/******************************************************************************* + * 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 Iter, typename Compare > + bool is_sorted(Iter first, Iter last, Compare comp) { + (void)first; + (void)last; + (void)comp; + return true; + } + + template < typename Iter, typename Compare > + bool is_sorted_unique(Iter first, Iter last, Compare comp) { + (void)first; + (void)last; + (void)comp; + return true; + } +} diff --git a/headers/flat.hpp/flat_fwd.hpp b/headers/flat.hpp/flat_fwd.hpp index 869022d..da10e37 100644 --- a/headers/flat.hpp/flat_fwd.hpp +++ b/headers/flat.hpp/flat_fwd.hpp @@ -14,12 +14,19 @@ #include #include +#include "detail/is_sorted.hpp" #include "detail/eq_compare.hpp" #include "detail/pair_compare.hpp" #include "detail/is_transparent.hpp" namespace flat_hpp { + struct sorted_range_t {}; + inline constexpr sorted_range_t sorted_range = sorted_range_t(); + + struct sorted_unique_range_t : public sorted_range_t {}; + inline constexpr sorted_unique_range_t sorted_unique_range = sorted_unique_range_t(); + template < typename Key , typename Compare = std::less , typename Container = std::vector > diff --git a/headers/flat.hpp/flat_map.hpp b/headers/flat.hpp/flat_map.hpp index c1a3679..6e285d0 100644 --- a/headers/flat.hpp/flat_map.hpp +++ b/headers/flat.hpp/flat_map.hpp @@ -75,18 +75,52 @@ namespace flat_hpp insert(first, last); } + template < typename InputIter > + flat_map(sorted_range_t, InputIter first, InputIter last) { + insert(sorted_range, first, last); + } + + template < typename InputIter > + flat_map(sorted_unique_range_t, InputIter first, InputIter last) { + insert(sorted_unique_range, first, last); + } + template < typename InputIter > flat_map(InputIter first, InputIter last, const Compare& c) : base_type(c) { insert(first, last); } + template < typename InputIter > + flat_map(sorted_range_t, InputIter first, InputIter last, const Compare& c) + : base_type(c) { + insert(sorted_range, first, last); + } + + template < typename InputIter > + flat_map(sorted_unique_range_t, InputIter first, InputIter last, const Compare& c) + : base_type(c) { + insert(sorted_unique_range, first, last); + } + template < typename InputIter, typename Allocator > flat_map(InputIter first, InputIter last, const Allocator& a) : data_(a) { insert(first, last); } + template < typename InputIter, typename Allocator > + flat_map(sorted_range_t, InputIter first, InputIter last, const Allocator& a) + : data_(a) { + insert(sorted_range, first, last); + } + + template < typename InputIter, typename Allocator > + flat_map(sorted_unique_range_t, InputIter first, InputIter last, const Allocator& a) + : data_(a) { + insert(sorted_unique_range, first, last); + } + template < typename InputIter , typename Allocator > flat_map(InputIter first, InputIter last, const Compare& c, const Allocator& a) : base_type(c) @@ -94,21 +128,65 @@ namespace flat_hpp insert(first, last); } + template < typename InputIter , typename Allocator > + flat_map(sorted_range_t, InputIter first, InputIter last, const Compare& c, const Allocator& a) + : base_type(c) + , data_(a) { + insert(sorted_range, first, last); + } + + template < typename InputIter , typename Allocator > + flat_map(sorted_unique_range_t, InputIter first, InputIter last, const Compare& c, const Allocator& a) + : base_type(c) + , data_(a) { + insert(sorted_unique_range, first, last); + } + flat_map(std::initializer_list ilist) { insert(ilist); } + flat_map(sorted_range_t, std::initializer_list ilist) { + insert(sorted_range, ilist); + } + + flat_map(sorted_unique_range_t, std::initializer_list ilist) { + insert(sorted_unique_range, ilist); + } + flat_map(std::initializer_list ilist, const Compare& c) : base_type(c) { insert(ilist); } + flat_map(sorted_range_t, std::initializer_list ilist, const Compare& c) + : base_type(c) { + insert(sorted_range, ilist); + } + + flat_map(sorted_unique_range_t, std::initializer_list ilist, const Compare& c) + : base_type(c) { + insert(sorted_unique_range, ilist); + } + template < typename Allocator > flat_map(std::initializer_list ilist, const Allocator& a) : data_(a) { insert(ilist); } + template < typename Allocator > + flat_map(sorted_range_t, std::initializer_list ilist, const Allocator& a) + : data_(a) { + insert(sorted_range, ilist); + } + + template < typename Allocator > + flat_map(sorted_unique_range_t, std::initializer_list ilist, const Allocator& a) + : data_(a) { + insert(sorted_unique_range, ilist); + } + template < typename Allocator > flat_map(std::initializer_list ilist, const Compare& c, const Allocator& a) : base_type(c) @@ -116,6 +194,20 @@ namespace flat_hpp insert(ilist); } + template < typename Allocator > + flat_map(sorted_range_t, std::initializer_list ilist, const Compare& c, const Allocator& a) + : base_type(c) + , data_(a) { + insert(sorted_range, ilist); + } + + template < typename Allocator > + flat_map(sorted_unique_range_t, std::initializer_list ilist, const Compare& c, const Allocator& a) + : base_type(c) + , data_(a) { + insert(sorted_unique_range, ilist); + } + template < typename Allocator > flat_map(flat_map&& other, const Allocator& a) : base_type(static_cast(other)) @@ -318,10 +410,25 @@ namespace flat_hpp data_.end()); } + template < typename InputIter > + void insert(sorted_range_t, InputIter first, InputIter last) { + assert(detail::is_sorted(first, last, value_comp())); + const auto mid_iter = data_.insert(data_.end(), first, last); + 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) { insert(ilist.begin(), ilist.end()); } + void insert(sorted_range_t, std::initializer_list ilist) { + insert(sorted_range, ilist.begin(), ilist.end()); + } + template < typename... Args > std::pair emplace(Args&&... args) { return insert(value_type(std::forward(args)...)); diff --git a/headers/flat.hpp/flat_multimap.hpp b/headers/flat.hpp/flat_multimap.hpp index 65bbc6b..3220571 100644 --- a/headers/flat.hpp/flat_multimap.hpp +++ b/headers/flat.hpp/flat_multimap.hpp @@ -75,18 +75,35 @@ namespace flat_hpp insert(first, last); } + template < typename InputIter > + flat_multimap(sorted_range_t, InputIter first, InputIter last) { + insert(sorted_range, first, last); + } + template < typename InputIter > flat_multimap(InputIter first, InputIter last, const Compare& c) : base_type(c) { insert(first, last); } + template < typename InputIter > + flat_multimap(sorted_range_t, InputIter first, InputIter last, const Compare& c) + : base_type(c) { + insert(sorted_range, first, last); + } + template < typename InputIter, typename Allocator > flat_multimap(InputIter first, InputIter last, const Allocator& a) : data_(a) { insert(first, last); } + template < typename InputIter, typename Allocator > + flat_multimap(sorted_range_t, InputIter first, InputIter last, const Allocator& a) + : data_(a) { + insert(sorted_range, first, last); + } + template < typename InputIter , typename Allocator > flat_multimap(InputIter first, InputIter last, const Compare& c, const Allocator& a) : base_type(c) @@ -94,21 +111,43 @@ namespace flat_hpp insert(first, last); } + template < typename InputIter , typename Allocator > + flat_multimap(sorted_range_t, InputIter first, InputIter last, const Compare& c, const Allocator& a) + : base_type(c) + , data_(a) { + insert(sorted_range, first, last); + } + flat_multimap(std::initializer_list ilist) { insert(ilist); } + flat_multimap(sorted_range_t, std::initializer_list ilist) { + insert(sorted_range, ilist); + } + flat_multimap(std::initializer_list ilist, const Compare& c) : base_type(c) { insert(ilist); } + flat_multimap(sorted_range_t, std::initializer_list ilist, const Compare& c) + : base_type(c) { + insert(sorted_range, ilist); + } + template < typename Allocator > flat_multimap(std::initializer_list ilist, const Allocator& a) : data_(a) { insert(ilist); } + template < typename Allocator > + flat_multimap(sorted_range_t, std::initializer_list ilist, const Allocator& a) + : data_(a) { + insert(sorted_range, ilist); + } + template < typename Allocator > flat_multimap(std::initializer_list ilist, const Compare& c, const Allocator& a) : base_type(c) @@ -116,6 +155,13 @@ namespace flat_hpp insert(ilist); } + template < typename Allocator > + flat_multimap(sorted_range_t, std::initializer_list ilist, const Compare& c, const Allocator& a) + : base_type(c) + , data_(a) { + insert(sorted_range, ilist); + } + template < typename Allocator > flat_multimap(flat_multimap&& other, const Allocator& a) : base_type(static_cast(other)) @@ -310,10 +356,21 @@ namespace flat_hpp std::inplace_merge(data_.begin(), mid_iter, data_.end()); } + template < typename InputIter > + void insert(sorted_range_t, InputIter first, InputIter last) { + assert(detail::is_sorted(first, last, value_comp())); + const auto mid_iter = data_.insert(data_.end(), first, last); + std::inplace_merge(data_.begin(), mid_iter, data_.end()); + } + void insert(std::initializer_list ilist) { insert(ilist.begin(), ilist.end()); } + void insert(sorted_range_t, std::initializer_list ilist) { + insert(sorted_range, ilist.begin(), ilist.end()); + } + template < typename... Args > iterator emplace(Args&&... args) { return insert(value_type(std::forward(args)...)); diff --git a/headers/flat.hpp/flat_multiset.hpp b/headers/flat.hpp/flat_multiset.hpp index 2ecc8df..e493603 100644 --- a/headers/flat.hpp/flat_multiset.hpp +++ b/headers/flat.hpp/flat_multiset.hpp @@ -57,18 +57,35 @@ namespace flat_hpp insert(first, last); } + template < typename InputIter > + flat_multiset(sorted_range_t, InputIter first, InputIter last) { + insert(sorted_range, first, last); + } + template < typename InputIter > flat_multiset(InputIter first, InputIter last, const Compare& c) : base_type(c) { insert(first, last); } + template < typename InputIter > + flat_multiset(sorted_range_t, InputIter first, InputIter last, const Compare& c) + : base_type(c) { + insert(sorted_range, first, last); + } + template < typename InputIter, typename Allocator > flat_multiset(InputIter first, InputIter last, const Allocator& a) : data_(a) { insert(first, last); } + template < typename InputIter, typename Allocator > + flat_multiset(sorted_range_t, InputIter first, InputIter last, const Allocator& a) + : data_(a) { + insert(sorted_range, first, last); + } + template < typename InputIter, typename Allocator > flat_multiset(InputIter first, InputIter last, const Compare& c, const Allocator& a) : base_type(c) @@ -76,21 +93,43 @@ namespace flat_hpp insert(first, last); } + template < typename InputIter, typename Allocator > + flat_multiset(sorted_range_t, InputIter first, InputIter last, const Compare& c, const Allocator& a) + : base_type(c) + , data_(a) { + insert(sorted_range, first, last); + } + flat_multiset(std::initializer_list ilist) { insert(ilist); } + flat_multiset(sorted_range_t, std::initializer_list ilist) { + insert(sorted_range, ilist); + } + flat_multiset(std::initializer_list ilist, const Compare& c) : base_type(c) { insert(ilist); } + flat_multiset(sorted_range_t, std::initializer_list ilist, const Compare& c) + : base_type(c) { + insert(sorted_range, ilist); + } + template < typename Allocator > flat_multiset(std::initializer_list ilist, const Allocator& a) : data_(a) { insert(ilist); } + template < typename Allocator > + flat_multiset(sorted_range_t, std::initializer_list ilist, const Allocator& a) + : data_(a) { + insert(sorted_range, ilist); + } + template < typename Allocator > flat_multiset(std::initializer_list ilist, const Compare& c, const Allocator& a) : base_type(c) @@ -98,6 +137,13 @@ namespace flat_hpp insert(ilist); } + template < typename Allocator > + flat_multiset(sorted_range_t, std::initializer_list ilist, const Compare& c, const Allocator& a) + : base_type(c) + , data_(a) { + insert(sorted_range, ilist); + } + template < typename Allocator > flat_multiset(flat_multiset&& other, const Allocator& a) : base_type(static_cast(other)) @@ -238,10 +284,21 @@ namespace flat_hpp std::inplace_merge(data_.begin(), mid_iter, data_.end()); } + template < typename InputIter > + void insert(sorted_range_t, InputIter first, InputIter last) { + assert(detail::is_sorted(first, last, value_comp())); + const auto mid_iter = data_.insert(data_.end(), first, last); + std::inplace_merge(data_.begin(), mid_iter, data_.end()); + } + void insert(std::initializer_list ilist) { insert(ilist.begin(), ilist.end()); } + void insert(sorted_range_t, std::initializer_list ilist) { + insert(sorted_range, ilist.begin(), ilist.end()); + } + template < typename... Args > iterator emplace(Args&&... args) { return insert(value_type(std::forward(args)...)); diff --git a/headers/flat.hpp/flat_set.hpp b/headers/flat.hpp/flat_set.hpp index 132ac9e..9e15a71 100644 --- a/headers/flat.hpp/flat_set.hpp +++ b/headers/flat.hpp/flat_set.hpp @@ -57,18 +57,52 @@ namespace flat_hpp insert(first, last); } + template < typename InputIter > + flat_set(sorted_range_t, InputIter first, InputIter last) { + insert(sorted_range, first, last); + } + + template < typename InputIter > + flat_set(sorted_unique_range_t, InputIter first, InputIter last) { + insert(sorted_unique_range, first, last); + } + template < typename InputIter > flat_set(InputIter first, InputIter last, const Compare& c) : base_type(c) { insert(first, last); } + template < typename InputIter > + flat_set(sorted_range_t, InputIter first, InputIter last, const Compare& c) + : base_type(c) { + insert(sorted_range, first, last); + } + + template < typename InputIter > + flat_set(sorted_unique_range_t, InputIter first, InputIter last, const Compare& c) + : base_type(c) { + insert(sorted_unique_range, first, last); + } + template < typename InputIter, typename Allocator > flat_set(InputIter first, InputIter last, const Allocator& a) : data_(a) { insert(first, last); } + template < typename InputIter, typename Allocator > + flat_set(sorted_range_t, InputIter first, InputIter last, const Allocator& a) + : data_(a) { + insert(sorted_range, first, last); + } + + template < typename InputIter, typename Allocator > + flat_set(sorted_unique_range_t, InputIter first, InputIter last, const Allocator& a) + : data_(a) { + insert(sorted_unique_range, first, last); + } + template < typename InputIter, typename Allocator > flat_set(InputIter first, InputIter last, const Compare& c, const Allocator& a) : base_type(c) @@ -76,21 +110,65 @@ namespace flat_hpp insert(first, last); } + template < typename InputIter, typename Allocator > + flat_set(sorted_range_t, InputIter first, InputIter last, const Compare& c, const Allocator& a) + : base_type(c) + , data_(a) { + insert(sorted_range, first, last); + } + + template < typename InputIter, typename Allocator > + flat_set(sorted_unique_range_t, InputIter first, InputIter last, const Compare& c, const Allocator& a) + : base_type(c) + , data_(a) { + insert(sorted_unique_range, first, last); + } + flat_set(std::initializer_list ilist) { insert(ilist); } + flat_set(sorted_range_t, std::initializer_list ilist) { + insert(sorted_range, ilist); + } + + flat_set(sorted_unique_range_t, std::initializer_list ilist) { + insert(sorted_unique_range, ilist); + } + flat_set(std::initializer_list ilist, const Compare& c) : base_type(c) { insert(ilist); } + flat_set(sorted_range_t, std::initializer_list ilist, const Compare& c) + : base_type(c) { + insert(sorted_range, ilist); + } + + flat_set(sorted_unique_range_t, std::initializer_list ilist, const Compare& c) + : base_type(c) { + insert(sorted_unique_range, ilist); + } + template < typename Allocator > flat_set(std::initializer_list ilist, const Allocator& a) : data_(a) { insert(ilist); } + template < typename Allocator > + flat_set(sorted_range_t, std::initializer_list ilist, const Allocator& a) + : data_(a) { + insert(sorted_range, ilist); + } + + template < typename Allocator > + flat_set(sorted_unique_range_t, std::initializer_list ilist, const Allocator& a) + : data_(a) { + insert(sorted_unique_range, ilist); + } + template < typename Allocator > flat_set(std::initializer_list ilist, const Compare& c, const Allocator& a) : base_type(c) @@ -98,6 +176,20 @@ namespace flat_hpp insert(ilist); } + template < typename Allocator > + flat_set(sorted_range_t, std::initializer_list ilist, const Compare& c, const Allocator& a) + : base_type(c) + , data_(a) { + insert(sorted_range, ilist); + } + + template < typename Allocator > + flat_set(sorted_unique_range_t, std::initializer_list ilist, const Compare& c, const Allocator& a) + : base_type(c) + , data_(a) { + insert(sorted_unique_range, ilist); + } + template < typename Allocator > flat_set(flat_set&& other, const Allocator& a) : base_type(static_cast(other)) @@ -246,10 +338,25 @@ namespace flat_hpp data_.end()); } + template < typename InputIter > + void insert(sorted_range_t, InputIter first, InputIter last) { + assert(detail::is_sorted(first, last, value_comp())); + const auto mid_iter = data_.insert(data_.end(), first, last); + 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) { insert(ilist.begin(), ilist.end()); } + void insert(sorted_range_t, std::initializer_list ilist) { + insert(sorted_range, ilist.begin(), ilist.end()); + } + template < typename... Args > std::pair emplace(Args&&... args) { return insert(value_type(std::forward(args)...)); diff --git a/untests/flat_map_tests.cpp b/untests/flat_map_tests.cpp index 72772c4..0cbbb4d 100644 --- a/untests/flat_map_tests.cpp +++ b/untests/flat_map_tests.cpp @@ -350,6 +350,16 @@ TEST_CASE("flat_map") { 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}}); } + + { + map_t s0; + s0.insert(sorted_unique_range, {{1,3},{2,2},{3,1}}); + REQUIRE(s0 == map_t{{1,3},{2,2},{3,1}}); + + map_t s1; + s1.insert(sorted_range, {{1,3},{2,2},{2,2},{3,1}}); + REQUIRE(s1 == map_t{{1,3},{2,2},{3,1}}); + } } SECTION("erasers") { using map_t = flat_map; diff --git a/untests/flat_multimap_tests.cpp b/untests/flat_multimap_tests.cpp index 6ba52b7..e37cd0a 100644 --- a/untests/flat_multimap_tests.cpp +++ b/untests/flat_multimap_tests.cpp @@ -350,6 +350,16 @@ TEST_CASE("flat_multimap") { 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}}); } + + { + map_t s0; + s0.insert(sorted_unique_range, {{1,3},{2,2},{3,1}}); + REQUIRE(s0 == map_t{{1,3},{2,2},{3,1}}); + + map_t s1; + s1.insert(sorted_range, {{1,3},{2,2},{2,2},{3,1}}); + REQUIRE(s1 == map_t{{1,3},{2,2},{2,2},{3,1}}); + } } SECTION("erasers") { using map_t = flat_multimap; diff --git a/untests/flat_multiset_tests.cpp b/untests/flat_multiset_tests.cpp index bee3325..efe483d 100644 --- a/untests/flat_multiset_tests.cpp +++ b/untests/flat_multiset_tests.cpp @@ -326,6 +326,16 @@ TEST_CASE("flat_multiset") { s0.insert({9,7,3,5,5}); REQUIRE(s0 == set_t{2,3,4,4,5,5,6,7,9}); } + + { + set_t s0; + s0.insert(sorted_unique_range, {1,2,3}); + REQUIRE(s0 == set_t{1,2,3}); + + set_t s1; + s1.insert(sorted_range, {1,2,2,3}); + REQUIRE(s1 == set_t{1,2,2,3}); + } } SECTION("erasers") { using set_t = flat_multiset; diff --git a/untests/flat_set_tests.cpp b/untests/flat_set_tests.cpp index ff1f939..b2f4a7f 100644 --- a/untests/flat_set_tests.cpp +++ b/untests/flat_set_tests.cpp @@ -326,6 +326,16 @@ TEST_CASE("flat_set") { s0.insert({9,7,3,5,5}); REQUIRE(s0 == set_t{2,3,4,5,6,7,9}); } + + { + set_t s0; + s0.insert(sorted_unique_range, {1,2,3}); + REQUIRE(s0 == set_t{1,2,3}); + + set_t s1; + s1.insert(sorted_range, {1,2,2,3}); + REQUIRE(s1 == set_t{1,2,3}); + } } SECTION("erasers") { using set_t = flat_set; From 8fe5c749ffbc3915c5c9942dc8b936fa7feb78e7 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Fri, 31 May 2019 08:52:32 +0700 Subject: [PATCH 4/7] add ctors from sorted ranges optimization --- headers/flat.hpp/flat_map.hpp | 125 +++++++++++++++++++---------- headers/flat.hpp/flat_multimap.hpp | 76 ++++++++++++------ headers/flat.hpp/flat_multiset.hpp | 72 +++++++++++------ headers/flat.hpp/flat_set.hpp | 119 ++++++++++++++++++--------- untests/flat_map_tests.cpp | 9 +++ untests/flat_multimap_tests.cpp | 9 +++ untests/flat_multiset_tests.cpp | 9 +++ untests/flat_set_tests.cpp | 9 +++ 8 files changed, 295 insertions(+), 133 deletions(-) diff --git a/headers/flat.hpp/flat_map.hpp b/headers/flat.hpp/flat_map.hpp index 6e285d0..27152f9 100644 --- a/headers/flat.hpp/flat_map.hpp +++ b/headers/flat.hpp/flat_map.hpp @@ -72,140 +72,140 @@ namespace flat_hpp template < typename InputIter > flat_map(InputIter first, InputIter last) { - insert(first, last); + from_range_(first, last); } template < typename InputIter > flat_map(sorted_range_t, InputIter first, InputIter last) { - insert(sorted_range, first, last); + from_range_(sorted_range, first, last); } template < typename InputIter > flat_map(sorted_unique_range_t, InputIter first, InputIter last) { - insert(sorted_unique_range, first, last); + from_range_(sorted_unique_range, first, last); } template < typename InputIter > flat_map(InputIter first, InputIter last, const Compare& c) : base_type(c) { - insert(first, last); + from_range_(first, last); } template < typename InputIter > flat_map(sorted_range_t, InputIter first, InputIter last, const Compare& c) : base_type(c) { - insert(sorted_range, first, last); + from_range_(sorted_range, first, last); } template < typename InputIter > flat_map(sorted_unique_range_t, InputIter first, InputIter last, const Compare& c) : base_type(c) { - insert(sorted_unique_range, first, last); + from_range_(sorted_unique_range, first, last); } template < typename InputIter, typename Allocator > flat_map(InputIter first, InputIter last, const Allocator& a) : data_(a) { - insert(first, last); + from_range_(first, last); } template < typename InputIter, typename Allocator > flat_map(sorted_range_t, InputIter first, InputIter last, const Allocator& a) : data_(a) { - insert(sorted_range, first, last); + from_range_(sorted_range, first, last); } template < typename InputIter, typename Allocator > flat_map(sorted_unique_range_t, InputIter first, InputIter last, const Allocator& a) : data_(a) { - insert(sorted_unique_range, first, last); + from_range_(sorted_unique_range, first, last); } - template < typename InputIter , typename Allocator > + template < typename InputIter, typename Allocator > flat_map(InputIter first, InputIter last, const Compare& c, const Allocator& a) : base_type(c) , data_(a) { - insert(first, last); + from_range_(first, last); } - template < typename InputIter , typename Allocator > + template < typename InputIter, typename Allocator > flat_map(sorted_range_t, InputIter first, InputIter last, const Compare& c, const Allocator& a) : base_type(c) , data_(a) { - insert(sorted_range, first, last); + from_range_(sorted_range, first, last); } - template < typename InputIter , typename Allocator > + template < typename InputIter, typename Allocator > flat_map(sorted_unique_range_t, InputIter first, InputIter last, const Compare& c, const Allocator& a) : base_type(c) , data_(a) { - insert(sorted_unique_range, first, last); + from_range_(sorted_unique_range, first, last); } flat_map(std::initializer_list ilist) { - insert(ilist); + from_range_(ilist.begin(), ilist.end()); } flat_map(sorted_range_t, std::initializer_list ilist) { - insert(sorted_range, ilist); + from_range_(sorted_range, ilist.begin(), ilist.end()); } flat_map(sorted_unique_range_t, std::initializer_list ilist) { - insert(sorted_unique_range, ilist); + from_range_(sorted_unique_range, ilist.begin(), ilist.end()); } flat_map(std::initializer_list ilist, const Compare& c) : base_type(c) { - insert(ilist); + from_range_(ilist.begin(), ilist.end()); } flat_map(sorted_range_t, std::initializer_list ilist, const Compare& c) : base_type(c) { - insert(sorted_range, ilist); + from_range_(sorted_range, ilist.begin(), ilist.end()); } flat_map(sorted_unique_range_t, std::initializer_list ilist, const Compare& c) : base_type(c) { - insert(sorted_unique_range, ilist); + from_range_(sorted_unique_range, ilist.begin(), ilist.end()); } template < typename Allocator > flat_map(std::initializer_list ilist, const Allocator& a) : data_(a) { - insert(ilist); + from_range_(ilist.begin(), ilist.end()); } template < typename Allocator > flat_map(sorted_range_t, std::initializer_list ilist, const Allocator& a) : data_(a) { - insert(sorted_range, ilist); + from_range_(sorted_range, ilist.begin(), ilist.end()); } template < typename Allocator > flat_map(sorted_unique_range_t, std::initializer_list ilist, const Allocator& a) : data_(a) { - insert(sorted_unique_range, ilist); + from_range_(sorted_unique_range, ilist.begin(), ilist.end()); } template < typename Allocator > flat_map(std::initializer_list ilist, const Compare& c, const Allocator& a) : base_type(c) , data_(a) { - insert(ilist); + from_range_(ilist.begin(), ilist.end()); } template < typename Allocator > flat_map(sorted_range_t, std::initializer_list ilist, const Compare& c, const Allocator& a) : base_type(c) , data_(a) { - insert(sorted_range, ilist); + from_range_(sorted_range, ilist.begin(), ilist.end()); } template < typename Allocator > flat_map(sorted_unique_range_t, std::initializer_list ilist, const Compare& c, const Allocator& a) : base_type(c) , data_(a) { - insert(sorted_unique_range, ilist); + from_range_(sorted_unique_range, ilist.begin(), ilist.end()); } template < typename Allocator > @@ -401,32 +401,20 @@ namespace flat_hpp template < typename InputIter > void insert(InputIter first, InputIter last) { - 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()); + insert_range_(first, last); } template < typename InputIter > void insert(sorted_range_t, InputIter first, InputIter last) { - assert(detail::is_sorted(first, last, value_comp())); - const auto mid_iter = data_.insert(data_.end(), first, last); - std::inplace_merge(data_.begin(), mid_iter, data_.end()); - data_.erase( - std::unique(data_.begin(), data_.end(), - detail::eq_compare(value_comp())), - data_.end()); + insert_range_(sorted_range, first, last); } void insert(std::initializer_list ilist) { - insert(ilist.begin(), ilist.end()); + insert_range_(ilist.begin(), ilist.end()); } void insert(sorted_range_t, std::initializer_list ilist) { - insert(sorted_range, ilist.begin(), ilist.end()); + insert_range_(sorted_range, ilist.begin(), ilist.end()); } template < typename... Args > @@ -611,6 +599,57 @@ namespace flat_hpp value_compare value_comp() const { return value_compare(key_comp()); } + private: + template < typename Iter > + void from_range_(Iter first, Iter last) { + assert(data_.empty()); + data_.insert(data_.end(), first, last); + std::sort(data_.begin(), data_.end(), value_comp()); + data_.erase( + std::unique(data_.begin(), data_.end(), + detail::eq_compare(value_comp())), + data_.end()); + } + + template < typename Iter > + void from_range_(sorted_range_t, Iter first, Iter last) { + assert(data_.empty()); + assert(detail::is_sorted(first, last, value_comp())); + data_.insert(data_.end(), first, last); + data_.erase( + std::unique(data_.begin(), data_.end(), + detail::eq_compare(value_comp())), + data_.end()); + } + + template < typename Iter > + void from_range_(sorted_unique_range_t, Iter first, Iter last) { + assert(data_.empty()); + assert(detail::is_sorted_unique(first, last, value_comp())); + data_.insert(data_.end(), first, last); + } + private: + template < typename Iter > + void insert_range_(Iter first, Iter last) { + 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()); + } + + template < typename Iter > + void insert_range_(sorted_range_t, Iter first, Iter last) { + assert(detail::is_sorted(first, last, value_comp())); + const auto mid_iter = data_.insert(data_.end(), first, last); + std::inplace_merge(data_.begin(), mid_iter, data_.end()); + data_.erase( + std::unique(data_.begin(), data_.end(), + detail::eq_compare(value_comp())), + data_.end()); + } private: container_type data_; }; diff --git a/headers/flat.hpp/flat_multimap.hpp b/headers/flat.hpp/flat_multimap.hpp index 3220571..3ef707f 100644 --- a/headers/flat.hpp/flat_multimap.hpp +++ b/headers/flat.hpp/flat_multimap.hpp @@ -72,94 +72,94 @@ namespace flat_hpp template < typename InputIter > flat_multimap(InputIter first, InputIter last) { - insert(first, last); + from_range_(first, last); } template < typename InputIter > flat_multimap(sorted_range_t, InputIter first, InputIter last) { - insert(sorted_range, first, last); + from_range_(sorted_range, first, last); } template < typename InputIter > flat_multimap(InputIter first, InputIter last, const Compare& c) : base_type(c) { - insert(first, last); + from_range_(first, last); } template < typename InputIter > flat_multimap(sorted_range_t, InputIter first, InputIter last, const Compare& c) : base_type(c) { - insert(sorted_range, first, last); + from_range_(sorted_range, first, last); } template < typename InputIter, typename Allocator > flat_multimap(InputIter first, InputIter last, const Allocator& a) : data_(a) { - insert(first, last); + from_range_(first, last); } template < typename InputIter, typename Allocator > flat_multimap(sorted_range_t, InputIter first, InputIter last, const Allocator& a) : data_(a) { - insert(sorted_range, first, last); + from_range_(sorted_range, first, last); } - template < typename InputIter , typename Allocator > + template < typename InputIter, typename Allocator > flat_multimap(InputIter first, InputIter last, const Compare& c, const Allocator& a) : base_type(c) , data_(a) { - insert(first, last); + from_range_(first, last); } - template < typename InputIter , typename Allocator > + template < typename InputIter, typename Allocator > flat_multimap(sorted_range_t, InputIter first, InputIter last, const Compare& c, const Allocator& a) : base_type(c) , data_(a) { - insert(sorted_range, first, last); + from_range_(sorted_range, first, last); } flat_multimap(std::initializer_list ilist) { - insert(ilist); + from_range_(ilist.begin(), ilist.end()); } flat_multimap(sorted_range_t, std::initializer_list ilist) { - insert(sorted_range, ilist); + from_range_(sorted_range, ilist.begin(), ilist.end()); } flat_multimap(std::initializer_list ilist, const Compare& c) : base_type(c) { - insert(ilist); + from_range_(ilist.begin(), ilist.end()); } flat_multimap(sorted_range_t, std::initializer_list ilist, const Compare& c) : base_type(c) { - insert(sorted_range, ilist); + from_range_(sorted_range, ilist.begin(), ilist.end()); } template < typename Allocator > flat_multimap(std::initializer_list ilist, const Allocator& a) : data_(a) { - insert(ilist); + from_range_(ilist.begin(), ilist.end()); } template < typename Allocator > flat_multimap(sorted_range_t, std::initializer_list ilist, const Allocator& a) : data_(a) { - insert(sorted_range, ilist); + from_range_(sorted_range, ilist.begin(), ilist.end()); } template < typename Allocator > flat_multimap(std::initializer_list ilist, const Compare& c, const Allocator& a) : base_type(c) , data_(a) { - insert(ilist); + from_range_(ilist.begin(), ilist.end()); } template < typename Allocator > flat_multimap(sorted_range_t, std::initializer_list ilist, const Compare& c, const Allocator& a) : base_type(c) , data_(a) { - insert(sorted_range, ilist); + from_range_(sorted_range, ilist.begin(), ilist.end()); } template < typename Allocator > @@ -351,24 +351,20 @@ namespace flat_hpp template < typename InputIter > void insert(InputIter first, InputIter last) { - 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()); + insert_range_(first, last); } template < typename InputIter > void insert(sorted_range_t, InputIter first, InputIter last) { - assert(detail::is_sorted(first, last, value_comp())); - const auto mid_iter = data_.insert(data_.end(), first, last); - std::inplace_merge(data_.begin(), mid_iter, data_.end()); + insert_range_(sorted_range, first, last); } void insert(std::initializer_list ilist) { - insert(ilist.begin(), ilist.end()); + insert_range_(ilist.begin(), ilist.end()); } void insert(sorted_range_t, std::initializer_list ilist) { - insert(sorted_range, ilist.begin(), ilist.end()); + insert_range_(sorted_range, ilist.begin(), ilist.end()); } template < typename... Args > @@ -553,6 +549,34 @@ namespace flat_hpp value_compare value_comp() const { return value_compare(key_comp()); } + private: + template < typename Iter > + void from_range_(Iter first, Iter last) { + assert(data_.empty()); + data_.insert(data_.end(), first, last); + std::sort(data_.begin(), data_.end(), value_comp()); + } + + template < typename Iter > + void from_range_(sorted_range_t, Iter first, Iter last) { + assert(data_.empty()); + assert(detail::is_sorted(first, last, value_comp())); + data_.insert(data_.end(), first, last); + } + private: + template < typename Iter > + void insert_range_(Iter first, Iter last) { + 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()); + } + + template < typename Iter > + void insert_range_(sorted_range_t, Iter first, Iter last) { + assert(detail::is_sorted(first, last, value_comp())); + const auto mid_iter = data_.insert(data_.end(), first, last); + std::inplace_merge(data_.begin(), mid_iter, data_.end()); + } private: container_type data_; }; diff --git a/headers/flat.hpp/flat_multiset.hpp b/headers/flat.hpp/flat_multiset.hpp index e493603..085e897 100644 --- a/headers/flat.hpp/flat_multiset.hpp +++ b/headers/flat.hpp/flat_multiset.hpp @@ -54,94 +54,94 @@ namespace flat_hpp template < typename InputIter > flat_multiset(InputIter first, InputIter last) { - insert(first, last); + from_range_(first, last); } template < typename InputIter > flat_multiset(sorted_range_t, InputIter first, InputIter last) { - insert(sorted_range, first, last); + from_range_(sorted_range, first, last); } template < typename InputIter > flat_multiset(InputIter first, InputIter last, const Compare& c) : base_type(c) { - insert(first, last); + from_range_(first, last); } template < typename InputIter > flat_multiset(sorted_range_t, InputIter first, InputIter last, const Compare& c) : base_type(c) { - insert(sorted_range, first, last); + from_range_(sorted_range, first, last); } template < typename InputIter, typename Allocator > flat_multiset(InputIter first, InputIter last, const Allocator& a) : data_(a) { - insert(first, last); + from_range_(first, last); } template < typename InputIter, typename Allocator > flat_multiset(sorted_range_t, InputIter first, InputIter last, const Allocator& a) : data_(a) { - insert(sorted_range, first, last); + from_range_(sorted_range, first, last); } template < typename InputIter, typename Allocator > flat_multiset(InputIter first, InputIter last, const Compare& c, const Allocator& a) : base_type(c) , data_(a) { - insert(first, last); + from_range_(first, last); } template < typename InputIter, typename Allocator > flat_multiset(sorted_range_t, InputIter first, InputIter last, const Compare& c, const Allocator& a) : base_type(c) , data_(a) { - insert(sorted_range, first, last); + from_range_(sorted_range, first, last); } flat_multiset(std::initializer_list ilist) { - insert(ilist); + from_range_(ilist.begin(), ilist.end()); } flat_multiset(sorted_range_t, std::initializer_list ilist) { - insert(sorted_range, ilist); + from_range_(sorted_range, ilist.begin(), ilist.end()); } flat_multiset(std::initializer_list ilist, const Compare& c) : base_type(c) { - insert(ilist); + from_range_(ilist.begin(), ilist.end()); } flat_multiset(sorted_range_t, std::initializer_list ilist, const Compare& c) : base_type(c) { - insert(sorted_range, ilist); + from_range_(sorted_range, ilist.begin(), ilist.end()); } template < typename Allocator > flat_multiset(std::initializer_list ilist, const Allocator& a) : data_(a) { - insert(ilist); + from_range_(ilist.begin(), ilist.end()); } template < typename Allocator > flat_multiset(sorted_range_t, std::initializer_list ilist, const Allocator& a) : data_(a) { - insert(sorted_range, ilist); + from_range_(sorted_range, ilist.begin(), ilist.end()); } template < typename Allocator > flat_multiset(std::initializer_list ilist, const Compare& c, const Allocator& a) : base_type(c) , data_(a) { - insert(ilist); + from_range_(ilist.begin(), ilist.end()); } template < typename Allocator > flat_multiset(sorted_range_t, std::initializer_list ilist, const Compare& c, const Allocator& a) : base_type(c) , data_(a) { - insert(sorted_range, ilist); + from_range_(sorted_range, ilist.begin(), ilist.end()); } template < typename Allocator > @@ -279,24 +279,20 @@ namespace flat_hpp template < typename InputIter > void insert(InputIter first, InputIter last) { - 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()); + insert_range_(first, last); } template < typename InputIter > void insert(sorted_range_t, InputIter first, InputIter last) { - assert(detail::is_sorted(first, last, value_comp())); - const auto mid_iter = data_.insert(data_.end(), first, last); - std::inplace_merge(data_.begin(), mid_iter, data_.end()); + insert_range_(sorted_range, first, last); } void insert(std::initializer_list ilist) { - insert(ilist.begin(), ilist.end()); + insert_range_(ilist.begin(), ilist.end()); } void insert(sorted_range_t, std::initializer_list ilist) { - insert(sorted_range, ilist.begin(), ilist.end()); + insert_range_(sorted_range, ilist.begin(), ilist.end()); } template < typename... Args > @@ -469,6 +465,34 @@ namespace flat_hpp value_compare value_comp() const { return value_compare(key_comp()); } + private: + template < typename Iter > + void from_range_(Iter first, Iter last) { + assert(data_.empty()); + data_.insert(data_.end(), first, last); + std::sort(data_.begin(), data_.end(), key_comp()); + } + + template < typename Iter > + void from_range_(sorted_range_t, Iter first, Iter last) { + assert(data_.empty()); + assert(detail::is_sorted(first, last, key_comp())); + data_.insert(data_.end(), first, last); + } + private: + template < typename Iter > + void insert_range_(Iter first, Iter last) { + const auto mid_iter = data_.insert(data_.end(), first, last); + std::sort(mid_iter, data_.end(), key_comp()); + std::inplace_merge(data_.begin(), mid_iter, data_.end()); + } + + template < typename Iter > + void insert_range_(sorted_range_t, Iter first, Iter last) { + assert(detail::is_sorted(first, last, key_comp())); + const auto mid_iter = data_.insert(data_.end(), first, last); + std::inplace_merge(data_.begin(), mid_iter, data_.end()); + } private: container_type data_; }; diff --git a/headers/flat.hpp/flat_set.hpp b/headers/flat.hpp/flat_set.hpp index 9e15a71..ff6c4d6 100644 --- a/headers/flat.hpp/flat_set.hpp +++ b/headers/flat.hpp/flat_set.hpp @@ -54,140 +54,140 @@ namespace flat_hpp template < typename InputIter > flat_set(InputIter first, InputIter last) { - insert(first, last); + from_range_(first, last); } template < typename InputIter > flat_set(sorted_range_t, InputIter first, InputIter last) { - insert(sorted_range, first, last); + from_range_(sorted_range, first, last); } template < typename InputIter > flat_set(sorted_unique_range_t, InputIter first, InputIter last) { - insert(sorted_unique_range, first, last); + from_range_(sorted_unique_range, first, last); } template < typename InputIter > flat_set(InputIter first, InputIter last, const Compare& c) : base_type(c) { - insert(first, last); + from_range_(first, last); } template < typename InputIter > flat_set(sorted_range_t, InputIter first, InputIter last, const Compare& c) : base_type(c) { - insert(sorted_range, first, last); + from_range_(sorted_range, first, last); } template < typename InputIter > flat_set(sorted_unique_range_t, InputIter first, InputIter last, const Compare& c) : base_type(c) { - insert(sorted_unique_range, first, last); + from_range_(sorted_unique_range, first, last); } template < typename InputIter, typename Allocator > flat_set(InputIter first, InputIter last, const Allocator& a) : data_(a) { - insert(first, last); + from_range_(first, last); } template < typename InputIter, typename Allocator > flat_set(sorted_range_t, InputIter first, InputIter last, const Allocator& a) : data_(a) { - insert(sorted_range, first, last); + from_range_(sorted_range, first, last); } template < typename InputIter, typename Allocator > flat_set(sorted_unique_range_t, InputIter first, InputIter last, const Allocator& a) : data_(a) { - insert(sorted_unique_range, first, last); + from_range_(sorted_unique_range, first, last); } template < typename InputIter, typename Allocator > flat_set(InputIter first, InputIter last, const Compare& c, const Allocator& a) : base_type(c) , data_(a) { - insert(first, last); + from_range_(first, last); } template < typename InputIter, typename Allocator > flat_set(sorted_range_t, InputIter first, InputIter last, const Compare& c, const Allocator& a) : base_type(c) , data_(a) { - insert(sorted_range, first, last); + from_range_(sorted_range, first, last); } template < typename InputIter, typename Allocator > flat_set(sorted_unique_range_t, InputIter first, InputIter last, const Compare& c, const Allocator& a) : base_type(c) , data_(a) { - insert(sorted_unique_range, first, last); + from_range_(sorted_unique_range, first, last); } flat_set(std::initializer_list ilist) { - insert(ilist); + from_range_(ilist.begin(), ilist.end()); } flat_set(sorted_range_t, std::initializer_list ilist) { - insert(sorted_range, ilist); + from_range_(sorted_range, ilist.begin(), ilist.end()); } flat_set(sorted_unique_range_t, std::initializer_list ilist) { - insert(sorted_unique_range, ilist); + from_range_(sorted_unique_range, ilist.begin(), ilist.end()); } flat_set(std::initializer_list ilist, const Compare& c) : base_type(c) { - insert(ilist); + from_range_(ilist.begin(), ilist.end()); } flat_set(sorted_range_t, std::initializer_list ilist, const Compare& c) : base_type(c) { - insert(sorted_range, ilist); + from_range_(sorted_range, ilist.begin(), ilist.end()); } flat_set(sorted_unique_range_t, std::initializer_list ilist, const Compare& c) : base_type(c) { - insert(sorted_unique_range, ilist); + from_range_(sorted_unique_range, ilist.begin(), ilist.end()); } template < typename Allocator > flat_set(std::initializer_list ilist, const Allocator& a) : data_(a) { - insert(ilist); + from_range_(ilist.begin(), ilist.end()); } template < typename Allocator > flat_set(sorted_range_t, std::initializer_list ilist, const Allocator& a) : data_(a) { - insert(sorted_range, ilist); + from_range_(sorted_range, ilist.begin(), ilist.end()); } template < typename Allocator > flat_set(sorted_unique_range_t, std::initializer_list ilist, const Allocator& a) : data_(a) { - insert(sorted_unique_range, ilist); + from_range_(sorted_unique_range, ilist.begin(), ilist.end()); } template < typename Allocator > flat_set(std::initializer_list ilist, const Compare& c, const Allocator& a) : base_type(c) , data_(a) { - insert(ilist); + from_range_(ilist.begin(), ilist.end()); } template < typename Allocator > flat_set(sorted_range_t, std::initializer_list ilist, const Compare& c, const Allocator& a) : base_type(c) , data_(a) { - insert(sorted_range, ilist); + from_range_(sorted_range, ilist.begin(), ilist.end()); } template < typename Allocator > flat_set(sorted_unique_range_t, std::initializer_list ilist, const Compare& c, const Allocator& a) : base_type(c) , data_(a) { - insert(sorted_unique_range, ilist); + from_range_(sorted_unique_range, ilist.begin(), ilist.end()); } template < typename Allocator > @@ -329,32 +329,20 @@ namespace flat_hpp template < typename InputIter > void insert(InputIter first, InputIter last) { - 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()); + insert_range_(first, last); } template < typename InputIter > void insert(sorted_range_t, InputIter first, InputIter last) { - assert(detail::is_sorted(first, last, value_comp())); - const auto mid_iter = data_.insert(data_.end(), first, last); - std::inplace_merge(data_.begin(), mid_iter, data_.end()); - data_.erase( - std::unique(data_.begin(), data_.end(), - detail::eq_compare(value_comp())), - data_.end()); + insert_range_(sorted_range, first, last); } void insert(std::initializer_list ilist) { - insert(ilist.begin(), ilist.end()); + insert_range_(ilist.begin(), ilist.end()); } void insert(sorted_range_t, std::initializer_list ilist) { - insert(sorted_range, ilist.begin(), ilist.end()); + insert_range_(sorted_range, ilist.begin(), ilist.end()); } template < typename... Args > @@ -527,6 +515,57 @@ namespace flat_hpp value_compare value_comp() const { return value_compare(key_comp()); } + private: + template < typename Iter > + void from_range_(Iter first, Iter last) { + assert(data_.empty()); + data_.insert(data_.end(), first, last); + std::sort(data_.begin(), data_.end(), key_comp()); + data_.erase( + std::unique(data_.begin(), data_.end(), + detail::eq_compare(key_comp())), + data_.end()); + } + + template < typename Iter > + void from_range_(sorted_range_t, Iter first, Iter last) { + assert(data_.empty()); + assert(detail::is_sorted(first, last, key_comp())); + data_.insert(data_.end(), first, last); + data_.erase( + std::unique(data_.begin(), data_.end(), + detail::eq_compare(key_comp())), + data_.end()); + } + + template < typename Iter > + void from_range_(sorted_unique_range_t, Iter first, Iter last) { + assert(data_.empty()); + assert(detail::is_sorted_unique(first, last, key_comp())); + data_.insert(data_.end(), first, last); + } + private: + template < typename Iter > + void insert_range_(Iter first, Iter last) { + const auto mid_iter = data_.insert(data_.end(), first, last); + std::sort(mid_iter, data_.end(), key_comp()); + std::inplace_merge(data_.begin(), mid_iter, data_.end()); + data_.erase( + std::unique(data_.begin(), data_.end(), + detail::eq_compare(key_comp())), + data_.end()); + } + + template < typename Iter > + void insert_range_(sorted_range_t, Iter first, Iter last) { + assert(detail::is_sorted(first, last, key_comp())); + const auto mid_iter = data_.insert(data_.end(), first, last); + std::inplace_merge(data_.begin(), mid_iter, data_.end()); + data_.erase( + std::unique(data_.begin(), data_.end(), + detail::eq_compare(key_comp())), + data_.end()); + } private: container_type data_; }; diff --git a/untests/flat_map_tests.cpp b/untests/flat_map_tests.cpp index 0cbbb4d..7ad0dc8 100644 --- a/untests/flat_map_tests.cpp +++ b/untests/flat_map_tests.cpp @@ -200,6 +200,15 @@ TEST_CASE("flat_map") { s3 = {{0,1}, {1,2}}; REQUIRE(s3 == map_t{{0,1}, {1,2}}); } + + { + auto s0 = map_t(sorted_range, {{1,4},{2,3},{2,2},{3,1}}); + REQUIRE(s0 == map_t{{1,4},{2,3},{3,1}}); + + vec_t v1({{1,4},{2,3},{2,2},{3,1}}); + auto s1 = map_t(sorted_range, v1.begin(), v1.end()); + REQUIRE(s1 == map_t{{1,4},{2,3},{3,1}}); + } } SECTION("capacity") { using map_t = flat_map; diff --git a/untests/flat_multimap_tests.cpp b/untests/flat_multimap_tests.cpp index e37cd0a..461a22b 100644 --- a/untests/flat_multimap_tests.cpp +++ b/untests/flat_multimap_tests.cpp @@ -200,6 +200,15 @@ TEST_CASE("flat_multimap") { s3 = {{0,1}, {1,2}}; REQUIRE(s3 == map_t{{0,1}, {1,2}}); } + + { + auto s0 = map_t(sorted_range, {{1,4},{2,3},{2,2},{3,1}}); + REQUIRE(s0 == map_t{{1,4},{2,3},{2,2},{3,1}}); + + vec_t v1({{1,4},{2,3},{2,2},{3,1}}); + auto s1 = map_t(sorted_range, v1.begin(), v1.end()); + REQUIRE(s1 == map_t{{1,4},{2,3},{2,2},{3,1}}); + } } SECTION("capacity") { using map_t = flat_multimap; diff --git a/untests/flat_multiset_tests.cpp b/untests/flat_multiset_tests.cpp index efe483d..2470283 100644 --- a/untests/flat_multiset_tests.cpp +++ b/untests/flat_multiset_tests.cpp @@ -186,6 +186,15 @@ TEST_CASE("flat_multiset") { s3 = {1,2,3}; REQUIRE(s3 == set_t{1,2,3}); } + + { + auto s0 = set_t(sorted_range, {1,2,2,3}); + REQUIRE(s0 == set_t{1,2,2,3}); + + vec_t v1({1,2,3,3}); + auto s1 = set_t(sorted_range, v1.begin(), v1.end()); + REQUIRE(s1 == set_t{1,2,3,3}); + } } SECTION("capacity") { using set_t = flat_multiset; diff --git a/untests/flat_set_tests.cpp b/untests/flat_set_tests.cpp index b2f4a7f..8b521b8 100644 --- a/untests/flat_set_tests.cpp +++ b/untests/flat_set_tests.cpp @@ -186,6 +186,15 @@ TEST_CASE("flat_set") { s3 = {1,2,3}; REQUIRE(s3 == set_t{1,2,3}); } + + { + auto s0 = set_t(sorted_unique_range, {1,2,3}); + REQUIRE(s0 == set_t{1,2,3}); + + vec_t v1({1,2,3}); + auto s1 = set_t(sorted_unique_range, v1.begin(), v1.end()); + REQUIRE(s1 == set_t{1,2,3}); + } } SECTION("capacity") { using set_t = flat_set; From 9038cd38e5e2d4377484ee1b1ff3646c492ed7a6 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Fri, 31 May 2019 09:18:59 +0700 Subject: [PATCH 5/7] impl debug assets for sorted ranges --- headers/flat.hpp/detail/is_sorted.hpp | 24 ++++++++++---- untests/flat_tests.cpp | 46 +++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 6 deletions(-) create mode 100644 untests/flat_tests.cpp diff --git a/headers/flat.hpp/detail/is_sorted.hpp b/headers/flat.hpp/detail/is_sorted.hpp index 7e63a49..7372c0c 100644 --- a/headers/flat.hpp/detail/is_sorted.hpp +++ b/headers/flat.hpp/detail/is_sorted.hpp @@ -10,17 +10,29 @@ namespace flat_hpp::detail { template < typename Iter, typename Compare > bool is_sorted(Iter first, Iter last, Compare comp) { - (void)first; - (void)last; - (void)comp; + if ( first != last ) { + Iter next = first; + while ( ++next != last ) { + if ( comp(*next, *first) ) { + return false; + } + ++first; + } + } return true; } template < typename Iter, typename Compare > bool is_sorted_unique(Iter first, Iter last, Compare comp) { - (void)first; - (void)last; - (void)comp; + if ( first != last ){ + Iter next = first; + while ( ++next != last ) { + if ( !comp(*first, *next) ) { + return false; + } + ++first; + } + } return true; } } diff --git a/untests/flat_tests.cpp b/untests/flat_tests.cpp new file mode 100644 index 0000000..2c1b046 --- /dev/null +++ b/untests/flat_tests.cpp @@ -0,0 +1,46 @@ +/******************************************************************************* + * 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) + ******************************************************************************/ + +#define CATCH_CONFIG_FAST_COMPILE +#include + +#include +using namespace flat_hpp; + +namespace +{ +} + +TEST_CASE("flat_map_detail") { + SECTION("is_sorted") { + auto i1 = {1,2,3,4}; + REQUIRE(detail::is_sorted(i1.begin(), i1.end(), std::less())); + REQUIRE_FALSE(detail::is_sorted(i1.begin(), i1.end(), std::greater())); + + auto i2 = {4,3,2,1}; + REQUIRE(detail::is_sorted(i2.begin(), i2.end(), std::greater())); + REQUIRE_FALSE(detail::is_sorted(i2.begin(), i2.end(), std::less())); + + auto i3 = {2,1,3,4}; + REQUIRE_FALSE(detail::is_sorted(i3.begin(), i3.end(), std::less())); + REQUIRE_FALSE(detail::is_sorted(i3.begin(), i3.end(), std::greater())); + } + SECTION("is_sorted_unique") { + auto i1 = {1,2,3,4}; + auto i1d = {1,2,2,3,4}; + REQUIRE(detail::is_sorted_unique(i1.begin(), i1.end(), std::less())); + REQUIRE_FALSE(detail::is_sorted_unique(i1d.begin(), i1d.end(), std::less())); + REQUIRE_FALSE(detail::is_sorted_unique(i1.begin(), i1.end(), std::greater())); + REQUIRE_FALSE(detail::is_sorted_unique(i1d.begin(), i1d.end(), std::greater())); + + auto i2 = {4,3,2,1}; + auto i2d = {4,3,2,1,1}; + REQUIRE(detail::is_sorted_unique(i2.begin(), i2.end(), std::greater())); + REQUIRE_FALSE(detail::is_sorted_unique(i2d.begin(), i2d.end(), std::greater())); + REQUIRE_FALSE(detail::is_sorted_unique(i2.begin(), i2.end(), std::less())); + REQUIRE_FALSE(detail::is_sorted_unique(i2d.begin(), i2d.end(), std::less())); + } +} From f34f7581ef15cd9b271523f19231431fe5fc1055 Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Fri, 31 May 2019 09:42:03 +0700 Subject: [PATCH 6/7] fix msvc warnings --- untests/flat_map_tests.cpp | 6 +++--- untests/flat_multimap_tests.cpp | 6 +++--- untests/flat_multiset_tests.cpp | 6 +++--- untests/flat_set_tests.cpp | 6 +++--- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/untests/flat_map_tests.cpp b/untests/flat_map_tests.cpp index 7ad0dc8..487daa0 100644 --- a/untests/flat_map_tests.cpp +++ b/untests/flat_map_tests.cpp @@ -218,13 +218,13 @@ TEST_CASE("flat_map") { REQUIRE(s0.empty()); REQUIRE_FALSE(s0.size()); - REQUIRE(s0.max_size() == std::allocator>().max_size()); + REQUIRE(s0.max_size() == std::vector>().max_size()); s0.insert({2,42}); REQUIRE_FALSE(s0.empty()); REQUIRE(s0.size() == 1u); - REQUIRE(s0.max_size() == std::allocator>().max_size()); + REQUIRE(s0.max_size() == std::vector>().max_size()); s0.insert({2,84}); REQUIRE(s0.size() == 1u); @@ -236,7 +236,7 @@ TEST_CASE("flat_map") { REQUIRE(s0.empty()); REQUIRE_FALSE(s0.size()); - REQUIRE(s0.max_size() == std::allocator>().max_size()); + REQUIRE(s0.max_size() == std::vector>().max_size()); } { diff --git a/untests/flat_multimap_tests.cpp b/untests/flat_multimap_tests.cpp index 461a22b..9a3f90d 100644 --- a/untests/flat_multimap_tests.cpp +++ b/untests/flat_multimap_tests.cpp @@ -218,13 +218,13 @@ TEST_CASE("flat_multimap") { REQUIRE(s0.empty()); REQUIRE_FALSE(s0.size()); - REQUIRE(s0.max_size() == std::allocator>().max_size()); + REQUIRE(s0.max_size() == std::vector>().max_size()); s0.insert({2,42}); REQUIRE_FALSE(s0.empty()); REQUIRE(s0.size() == 1u); - REQUIRE(s0.max_size() == std::allocator>().max_size()); + REQUIRE(s0.max_size() == std::vector>().max_size()); s0.insert({2,84}); REQUIRE(s0.size() == 2u); @@ -236,7 +236,7 @@ TEST_CASE("flat_multimap") { REQUIRE(s0.empty()); REQUIRE_FALSE(s0.size()); - REQUIRE(s0.max_size() == std::allocator>().max_size()); + REQUIRE(s0.max_size() == std::vector>().max_size()); } { diff --git a/untests/flat_multiset_tests.cpp b/untests/flat_multiset_tests.cpp index 2470283..aba9eea 100644 --- a/untests/flat_multiset_tests.cpp +++ b/untests/flat_multiset_tests.cpp @@ -204,13 +204,13 @@ TEST_CASE("flat_multiset") { REQUIRE(s0.empty()); REQUIRE_FALSE(s0.size()); - REQUIRE(s0.max_size() == std::allocator().max_size()); + REQUIRE(s0.max_size() == std::vector().max_size()); s0.insert(42); REQUIRE_FALSE(s0.empty()); REQUIRE(s0.size() == 1u); - REQUIRE(s0.max_size() == std::allocator().max_size()); + REQUIRE(s0.max_size() == std::vector().max_size()); s0.insert(42); REQUIRE(s0.size() == 2u); @@ -222,7 +222,7 @@ TEST_CASE("flat_multiset") { REQUIRE(s0.empty()); REQUIRE_FALSE(s0.size()); - REQUIRE(s0.max_size() == std::allocator().max_size()); + REQUIRE(s0.max_size() == std::vector().max_size()); } { diff --git a/untests/flat_set_tests.cpp b/untests/flat_set_tests.cpp index 8b521b8..ebbb99d 100644 --- a/untests/flat_set_tests.cpp +++ b/untests/flat_set_tests.cpp @@ -204,13 +204,13 @@ TEST_CASE("flat_set") { REQUIRE(s0.empty()); REQUIRE_FALSE(s0.size()); - REQUIRE(s0.max_size() == std::allocator().max_size()); + REQUIRE(s0.max_size() == std::vector().max_size()); s0.insert(42); REQUIRE_FALSE(s0.empty()); REQUIRE(s0.size() == 1u); - REQUIRE(s0.max_size() == std::allocator().max_size()); + REQUIRE(s0.max_size() == std::vector().max_size()); s0.insert(42); REQUIRE(s0.size() == 1u); @@ -222,7 +222,7 @@ TEST_CASE("flat_set") { REQUIRE(s0.empty()); REQUIRE_FALSE(s0.size()); - REQUIRE(s0.max_size() == std::allocator().max_size()); + REQUIRE(s0.max_size() == std::vector().max_size()); } { From 16e6a2d082078002a1721e7651803323614dc19f Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Fri, 31 May 2019 10:18:38 +0700 Subject: [PATCH 7/7] fix range merging order bug --- headers/flat.hpp/flat_map.hpp | 4 ++-- headers/flat.hpp/flat_multimap.hpp | 4 ++-- headers/flat.hpp/flat_multiset.hpp | 4 ++-- headers/flat.hpp/flat_set.hpp | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/headers/flat.hpp/flat_map.hpp b/headers/flat.hpp/flat_map.hpp index 27152f9..25eb9b3 100644 --- a/headers/flat.hpp/flat_map.hpp +++ b/headers/flat.hpp/flat_map.hpp @@ -633,7 +633,7 @@ namespace flat_hpp void insert_range_(Iter first, Iter last) { 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()); + std::inplace_merge(data_.begin(), mid_iter, data_.end(), value_comp()); data_.erase( std::unique(data_.begin(), data_.end(), detail::eq_compare(value_comp())), @@ -644,7 +644,7 @@ namespace flat_hpp void insert_range_(sorted_range_t, Iter first, Iter last) { assert(detail::is_sorted(first, last, value_comp())); const auto mid_iter = data_.insert(data_.end(), first, last); - std::inplace_merge(data_.begin(), mid_iter, data_.end()); + std::inplace_merge(data_.begin(), mid_iter, data_.end(), value_comp()); data_.erase( std::unique(data_.begin(), data_.end(), detail::eq_compare(value_comp())), diff --git a/headers/flat.hpp/flat_multimap.hpp b/headers/flat.hpp/flat_multimap.hpp index 3ef707f..580435d 100644 --- a/headers/flat.hpp/flat_multimap.hpp +++ b/headers/flat.hpp/flat_multimap.hpp @@ -568,14 +568,14 @@ namespace flat_hpp void insert_range_(Iter first, Iter last) { 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()); + std::inplace_merge(data_.begin(), mid_iter, data_.end(), value_comp()); } template < typename Iter > void insert_range_(sorted_range_t, Iter first, Iter last) { assert(detail::is_sorted(first, last, value_comp())); const auto mid_iter = data_.insert(data_.end(), first, last); - std::inplace_merge(data_.begin(), mid_iter, data_.end()); + std::inplace_merge(data_.begin(), mid_iter, data_.end(), value_comp()); } private: container_type data_; diff --git a/headers/flat.hpp/flat_multiset.hpp b/headers/flat.hpp/flat_multiset.hpp index 085e897..ae1fcb1 100644 --- a/headers/flat.hpp/flat_multiset.hpp +++ b/headers/flat.hpp/flat_multiset.hpp @@ -484,14 +484,14 @@ namespace flat_hpp void insert_range_(Iter first, Iter last) { const auto mid_iter = data_.insert(data_.end(), first, last); std::sort(mid_iter, data_.end(), key_comp()); - std::inplace_merge(data_.begin(), mid_iter, data_.end()); + std::inplace_merge(data_.begin(), mid_iter, data_.end(), key_comp()); } template < typename Iter > void insert_range_(sorted_range_t, Iter first, Iter last) { assert(detail::is_sorted(first, last, key_comp())); const auto mid_iter = data_.insert(data_.end(), first, last); - std::inplace_merge(data_.begin(), mid_iter, data_.end()); + std::inplace_merge(data_.begin(), mid_iter, data_.end(), key_comp()); } private: container_type data_; diff --git a/headers/flat.hpp/flat_set.hpp b/headers/flat.hpp/flat_set.hpp index ff6c4d6..18ca0aa 100644 --- a/headers/flat.hpp/flat_set.hpp +++ b/headers/flat.hpp/flat_set.hpp @@ -549,7 +549,7 @@ namespace flat_hpp void insert_range_(Iter first, Iter last) { const auto mid_iter = data_.insert(data_.end(), first, last); std::sort(mid_iter, data_.end(), key_comp()); - std::inplace_merge(data_.begin(), mid_iter, data_.end()); + std::inplace_merge(data_.begin(), mid_iter, data_.end(), key_comp()); data_.erase( std::unique(data_.begin(), data_.end(), detail::eq_compare(key_comp())), @@ -560,7 +560,7 @@ namespace flat_hpp void insert_range_(sorted_range_t, Iter first, Iter last) { assert(detail::is_sorted(first, last, key_comp())); const auto mid_iter = data_.insert(data_.end(), first, last); - std::inplace_merge(data_.begin(), mid_iter, data_.end()); + std::inplace_merge(data_.begin(), mid_iter, data_.end(), key_comp()); data_.erase( std::unique(data_.begin(), data_.end(), detail::eq_compare(key_comp())),