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/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/detail/is_sorted.hpp b/headers/flat.hpp/detail/is_sorted.hpp new file mode 100644 index 0000000..7372c0c --- /dev/null +++ b/headers/flat.hpp/detail/is_sorted.hpp @@ -0,0 +1,38 @@ +/******************************************************************************* + * 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) { + 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) { + if ( first != last ){ + Iter next = first; + while ( ++next != last ) { + if ( !comp(*first, *next) ) { + return false; + } + ++first; + } + } + return true; + } +} diff --git a/headers/flat.hpp/flat_fwd.hpp b/headers/flat.hpp/flat_fwd.hpp new file mode 100644 index 0000000..da10e37 --- /dev/null +++ b/headers/flat.hpp/flat_fwd.hpp @@ -0,0 +1,51 @@ +/******************************************************************************* + * 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/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 > + 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 fef0b96..25eb9b3 100644 --- a/headers/flat.hpp/flat_map.hpp +++ b/headers/flat.hpp/flat_map.hpp @@ -6,24 +6,14 @@ #pragma once -#include -#include -#include -#include -#include -#include -#include -#include - -#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, @@ -82,48 +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) { + from_range_(sorted_range, first, last); + } + + template < typename InputIter > + flat_map(sorted_unique_range_t, InputIter first, InputIter 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) { + 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) { + 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 > + template < typename InputIter, typename Allocator > + flat_map(sorted_range_t, InputIter first, InputIter last, const Allocator& a) + : data_(a) { + 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) { + from_range_(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) , data_(a) { - insert(first, last); + from_range_(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) { + from_range_(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) { + 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) { + from_range_(sorted_range, ilist.begin(), ilist.end()); + } + + flat_map(sorted_unique_range_t, std::initializer_list 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) { + from_range_(sorted_range, ilist.begin(), ilist.end()); + } + + flat_map(sorted_unique_range_t, std::initializer_list ilist, const Compare& c) + : base_type(c) { + 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) { + 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) { + 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) { + 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) { + from_range_(sorted_unique_range, ilist.begin(), ilist.end()); } template < typename Allocator > @@ -319,13 +401,20 @@ namespace flat_hpp template < typename InputIter > void insert(InputIter first, InputIter last) { - while ( first != last ) { - insert(*first++); - } + insert_range_(first, last); + } + + template < typename InputIter > + void insert(sorted_range_t, InputIter first, InputIter last) { + 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_range_(sorted_range, ilist.begin(), ilist.end()); } template < typename... Args > @@ -510,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(), value_comp()); + 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(), value_comp()); + 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 2977061..580435d 100644 --- a/headers/flat.hpp/flat_multimap.hpp +++ b/headers/flat.hpp/flat_multimap.hpp @@ -6,24 +6,14 @@ #pragma once -#include -#include -#include -#include -#include -#include -#include -#include - -#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, @@ -82,48 +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) { + 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) { + 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 > + template < typename InputIter, typename Allocator > + flat_multimap(sorted_range_t, InputIter first, InputIter last, const Allocator& a) + : data_(a) { + from_range_(sorted_range, first, last); + } + + 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 > + flat_multimap(sorted_range_t, InputIter first, InputIter last, const Compare& c, const Allocator& a) + : base_type(c) + , data_(a) { + 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) { + 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) { + 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) { + 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) { + from_range_(sorted_range, ilist.begin(), ilist.end()); } template < typename Allocator > @@ -315,13 +351,20 @@ namespace flat_hpp template < typename InputIter > void insert(InputIter first, InputIter last) { - while ( first != last ) { - insert(*first++); - } + insert_range_(first, last); + } + + template < typename InputIter > + void insert(sorted_range_t, InputIter first, InputIter last) { + 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_range_(sorted_range, ilist.begin(), ilist.end()); } template < typename... Args > @@ -506,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(), 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(), value_comp()); + } private: container_type data_; }; diff --git a/headers/flat.hpp/flat_multiset.hpp b/headers/flat.hpp/flat_multiset.hpp index 52f2531..ae1fcb1 100644 --- a/headers/flat.hpp/flat_multiset.hpp +++ b/headers/flat.hpp/flat_multiset.hpp @@ -6,22 +6,13 @@ #pragma once -#include -#include -#include -#include -#include -#include -#include -#include - -#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: @@ -63,48 +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) { + 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) { + 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) { + 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) { + 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) { + 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) { + 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) { + 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) { + from_range_(sorted_range, ilist.begin(), ilist.end()); } template < typename Allocator > @@ -242,13 +279,20 @@ namespace flat_hpp template < typename InputIter > void insert(InputIter first, InputIter last) { - while ( first != last ) { - insert(*first++); - } + insert_range_(first, last); + } + + template < typename InputIter > + void insert(sorted_range_t, InputIter first, InputIter last) { + 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_range_(sorted_range, ilist.begin(), ilist.end()); } template < typename... Args > @@ -421,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(), 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(), key_comp()); + } private: container_type data_; }; diff --git a/headers/flat.hpp/flat_set.hpp b/headers/flat.hpp/flat_set.hpp index aacd2e9..18ca0aa 100644 --- a/headers/flat.hpp/flat_set.hpp +++ b/headers/flat.hpp/flat_set.hpp @@ -6,22 +6,13 @@ #pragma once -#include -#include -#include -#include -#include -#include -#include -#include - -#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: @@ -63,48 +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) { + from_range_(sorted_range, first, last); + } + + template < typename InputIter > + flat_set(sorted_unique_range_t, InputIter first, InputIter 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) { + 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) { + 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) { + 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) { + 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) { + 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) { + 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) { + from_range_(sorted_range, ilist.begin(), ilist.end()); + } + + flat_set(sorted_unique_range_t, std::initializer_list 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) { + from_range_(sorted_range, ilist.begin(), ilist.end()); + } + + flat_set(sorted_unique_range_t, std::initializer_list ilist, const Compare& c) + : base_type(c) { + 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) { + 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) { + 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) { + 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) { + from_range_(sorted_unique_range, ilist.begin(), ilist.end()); } template < typename Allocator > @@ -246,13 +329,20 @@ namespace flat_hpp template < typename InputIter > void insert(InputIter first, InputIter last) { - while ( first != last ) { - insert(*first++); - } + insert_range_(first, last); + } + + template < typename InputIter > + void insert(sorted_range_t, InputIter first, InputIter last) { + 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_range_(sorted_range, ilist.begin(), ilist.end()); } template < typename... Args > @@ -425,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(), key_comp()); + 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(), key_comp()); + 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 b0c2c6c..487daa0 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; @@ -209,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); @@ -227,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()); } { @@ -342,6 +351,24 @@ 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}}); + } + + { + 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 d7f9dbe..9a3f90d 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; @@ -209,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); @@ -227,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()); } { @@ -342,6 +351,24 @@ 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}}); + } + + { + 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 8864239..aba9eea 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; @@ -195,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); @@ -213,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()); } { @@ -318,6 +327,24 @@ 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}); + } + + { + 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 91c59f1..ebbb99d 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; @@ -195,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); @@ -213,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()); } { @@ -318,6 +327,24 @@ 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}); + } + + { + 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; 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())); + } +}