From 8104ebd598e96533bd0ca89cf3aeb0f7547c1f9c Mon Sep 17 00:00:00 2001 From: BlackMATov Date: Fri, 31 May 2019 07:19:53 +0700 Subject: [PATCH] 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;