first flat_set impl

This commit is contained in:
2019-05-04 15:26:29 +07:00
parent d4e8598777
commit 8bf9a3f66d
2 changed files with 259 additions and 95 deletions

View File

@@ -78,19 +78,19 @@ namespace flat_hpp
} }
flat_set( flat_set(
std::initializer_list<value_type> il, std::initializer_list<value_type> ilist,
const Allocator& a) const Allocator& a)
: data_(a) { : data_(a) {
insert(il.begin(), il.end()); insert(ilist);
} }
flat_set( flat_set(
std::initializer_list<value_type> il, std::initializer_list<value_type> ilist,
const Compare& c = Compare(), const Compare& c = Compare(),
const Allocator& a = Allocator()) const Allocator& a = Allocator())
: data_(a) : data_(a)
, compare_(c) { , compare_(c) {
insert(il.begin(), il.end()); insert(ilist);
} }
iterator begin() noexcept { return data_.begin(); } iterator begin() noexcept { return data_.begin(); }
@@ -121,36 +121,52 @@ namespace flat_hpp
return data_.max_size(); return data_.max_size();
} }
template < typename P std::pair<iterator, bool> insert(value_type&& value) {
, typename = std::enable_if_t<std::is_constructible<value_type, P>::value> > const iterator iter = lower_bound(value);
std::pair<iterator, bool> insert(P&& p) { return iter == end() || compare_(value, *iter)
//TODO(BlackMat): implme ? std::make_pair(data_.insert(iter, std::move(value)), true)
return std::make_pair(end(), false); : std::make_pair(iter, false);
} }
template < typename P std::pair<iterator, bool> insert(const value_type& value) {
, typename = std::enable_if_t<std::is_constructible<value_type, P>::value> > const iterator iter = lower_bound(value);
std::pair<iterator, bool> insert(const_iterator hint, P&& p) { return iter == end() || compare_(value, *iter)
//TODO(BlackMat): implme ? std::make_pair(data_.insert(iter, value), true)
return std::make_pair(end(), false); : std::make_pair(iter, false);
}
iterator insert(const_iterator hint, value_type&& value) {
return (hint == begin() || compare_(*(hint - 1), value))
&& (hint == end() || compare_(value, *hint))
? data_.insert(hint, std::move(value))
: insert(std::move(value)).first;
}
iterator insert(const_iterator hint, const value_type& value) {
return (hint == begin() || compare_(*(hint - 1), value))
&& (hint == end() || compare_(value, *hint))
? data_.insert(hint, value)
: insert(value).first;
} }
template < typename InputIter > template < typename InputIter >
void insert(InputIter first, InputIter last) { void insert(InputIter first, InputIter last) {
for ( auto iter = first; iter != last; ++iter ) { while ( first != last ) {
insert(*iter); insert(*first++);
} }
} }
void insert(std::initializer_list<value_type> ilist) {
insert(ilist.begin(), ilist.end());
}
template < typename... Args > template < typename... Args >
std::pair<iterator, bool> emplace(Args&&... args) { std::pair<iterator, bool> emplace(Args&&... args) {
//TODO(BlackMat): implme
return insert(value_type(std::forward<Args>(args)...)); return insert(value_type(std::forward<Args>(args)...));
} }
template < typename... Args > template < typename... Args >
std::pair<iterator, bool> emplace_hint(const_iterator hint, Args&&... args) { iterator emplace_hint(const_iterator hint, Args&&... args) {
//TODO(BlackMat): implme
return insert(hint, value_type(std::forward<Args>(args)...)); return insert(hint, value_type(std::forward<Args>(args)...));
} }
@@ -159,67 +175,67 @@ namespace flat_hpp
} }
iterator erase(const_iterator iter) { iterator erase(const_iterator iter) {
//TODO(BlackMat): implme return data_.erase(iter);
return end();
} }
iterator erase(const_iterator first, const_iterator last) { iterator erase(const_iterator first, const_iterator last) {
//TODO(BlackMat): implme return data_.erase(first, last);
return end();
} }
iterator erase(const key_type& key) { size_type erase(const key_type& key) {
//TODO(BlackMat): implme const iterator iter = find(key);
return end(); return iter != end()
? (erase(iter), 1)
: 0;
} }
void swap(flat_set& other) { void swap(flat_set& other) {
//TODO(BlackMat): implme using std::swap;
swap(data_, other.data_);
swap(compare_, other.compare_);
} }
size_type count(const key_type& key) const { size_type count(const key_type& key) const {
const auto iter = find(key); const const_iterator iter = find(key);
return iter != end() ? 1 : 0; return iter != end() ? 1 : 0;
} }
iterator find(const key_type& key) { iterator find(const key_type& key) {
//TODO(BlackMat): implme const iterator iter = lower_bound(key);
return end(); return iter != end() && !compare_(key, *iter)
? iter
: end();
} }
const_iterator find(const key_type& key) const { const_iterator find(const key_type& key) const {
//TODO(BlackMat): implme const const_iterator iter = lower_bound(key);
return end(); return iter != end() && !compare_(key, *iter)
? iter
: end();
} }
std::pair<iterator, iterator> equal_range(const key_type& key) { std::pair<iterator, iterator> equal_range(const key_type& key) {
//TODO(BlackMat): implme return std::equal_range(begin(), end(), key, compare_);
return {end(), end()};
} }
std::pair<const_iterator, const_iterator> equal_range(const key_type& key) const { std::pair<const_iterator, const_iterator> equal_range(const key_type& key) const {
//TODO(BlackMat): implme return std::equal_range(begin(), end(), key, compare_);
return {end(), end()};
} }
iterator lower_bound(const key_type& key) { iterator lower_bound(const key_type& key) {
//TODO(BlackMat): implme return std::lower_bound(begin(), end(), key, compare_);
return end();
} }
const_iterator lower_bound(const key_type& key) const { const_iterator lower_bound(const key_type& key) const {
//TODO(BlackMat): implme return std::lower_bound(begin(), end(), key, compare_);
return end();
} }
iterator upper_bound(const key_type& key) { iterator upper_bound(const key_type& key) {
//TODO(BlackMat): implme return std::upper_bound(begin(), end(), key, compare_);
return end();
} }
const_iterator upper_bound(const key_type& key) const { const_iterator upper_bound(const key_type& key) const {
//TODO(BlackMat): implme return std::upper_bound(begin(), end(), key, compare_);
return end();
} }
key_compare key_comp() const { key_compare key_comp() const {

View File

@@ -18,13 +18,12 @@ namespace
using value_type = T; using value_type = T;
T* allocate(std::size_t n) { T* allocate(std::size_t n) {
(void)n; return static_cast<T*>(std::malloc(sizeof(T) * n));
return nullptr;
} }
void deallocate(T* p, std::size_t n) { void deallocate(T* p, std::size_t n) {
(void)p;
(void)n; (void)n;
std::free(p);
} }
}; };
@@ -69,95 +68,244 @@ TEST_CASE("flat_set") {
SECTION("ctors") { SECTION("ctors") {
using alloc_t = dummy_allocator<int>; using alloc_t = dummy_allocator<int>;
using set_t = flat_set<int, std::less<int>, alloc_t>; using set_t = flat_set<int, std::less<int>, alloc_t>;
using set2_t = flat_set<int, std::greater<int>, alloc_t>;
{ {
auto s0 = set_t(); auto s0 = set_t();
auto s1 = set_t(alloc_t()); auto s1 = set2_t(alloc_t());
auto s2 = set_t(std::less<int>()); auto s2 = set_t(std::less<int>());
auto s3 = set_t(std::less<int>(), alloc_t()); auto s3 = set2_t(std::greater<int>(), alloc_t());
} }
{ {
std::vector<int> v; std::vector<int> v{1,2,3};
auto s0 = set_t(v.cbegin(), v.cend()); auto s0 = set_t(v.cbegin(), v.cend());
auto s1 = set_t(v.cbegin(), v.cend(), alloc_t()); auto s1 = set2_t(v.cbegin(), v.cend(), alloc_t());
auto s2 = set_t(v.cbegin(), v.cend(), std::less<int>()); auto s2 = set_t(v.cbegin(), v.cend(), std::less<int>());
auto s3 = set_t(v.cbegin(), v.cend(), std::less<int>(), alloc_t()); auto s3 = set2_t(v.cbegin(), v.cend(), std::greater<int>(), alloc_t());
REQUIRE(std::vector<int>(s0.begin(), s0.end()) == std::vector<int>({1,2,3}));
REQUIRE(std::vector<int>(s1.begin(), s1.end()) == std::vector<int>({3,2,1}));
REQUIRE(std::vector<int>(s2.begin(), s2.end()) == std::vector<int>({1,2,3}));
REQUIRE(std::vector<int>(s3.begin(), s3.end()) == std::vector<int>({3,2,1}));
} }
{ {
auto s0 = set_t({0,1,2}); auto s0 = set_t({0,1,2});
auto s1 = set_t({0,1,2}, alloc_t()); auto s1 = set2_t({0,1,2}, alloc_t());
auto s2 = set_t({0,1,2}, std::less<int>()); auto s2 = set_t({0,1,2}, std::less<int>());
auto s3 = set_t({0,1,2}, std::less<int>(), alloc_t()); auto s3 = set2_t({0,1,2}, std::greater<int>(), alloc_t());
REQUIRE(std::vector<int>(s0.begin(), s0.end()) == std::vector<int>({0,1,2}));
REQUIRE(std::vector<int>(s1.begin(), s1.end()) == std::vector<int>({2,1,0}));
REQUIRE(std::vector<int>(s2.begin(), s2.end()) == std::vector<int>({0,1,2}));
REQUIRE(std::vector<int>(s3.begin(), s3.end()) == std::vector<int>({2,1,0}));
} }
} }
SECTION("capacity") { SECTION("capacity") {
using set_t = flat_set<int>; using set_t = flat_set<int>;
set_t s0; set_t s0;
s0.empty();
s0.size(); REQUIRE(s0.empty());
s0.max_size(); REQUIRE_FALSE(s0.size());
REQUIRE(s0.max_size() == std::allocator<int>().max_size());
s0.insert(42);
REQUIRE_FALSE(s0.empty());
REQUIRE(s0.size() == 1u);
REQUIRE(s0.max_size() == std::allocator<int>().max_size());
s0.insert(42);
REQUIRE(s0.size() == 1u);
s0.insert(84);
REQUIRE(s0.size() == 2u);
s0.clear();
REQUIRE(s0.empty());
REQUIRE_FALSE(s0.size());
REQUIRE(s0.max_size() == std::allocator<int>().max_size());
} }
SECTION("inserts") { SECTION("inserts") {
struct obj_t { struct obj_t {
obj_t(int i) : i(i) {} obj_t(int i) : i(i) {}
int i; int i;
bool operator<(const obj_t& o) const {
return i < o.i;
}
bool operator==(const obj_t& o) const {
return i == o.i;
}
}; };
using set_t = flat_set<obj_t>; using set_t = flat_set<obj_t>;
{ {
set_t s0; set_t s0;
s0.insert(42);
s0.insert(obj_t(42)); auto i0 = s0.insert(1);
s0.insert(s0.cend(), 84); REQUIRE(s0 == set_t{1});
s0.insert(s0.cend(), obj_t(84)); REQUIRE(i0 == std::make_pair(s0.begin(), true));
s0.emplace(100500);
s0.emplace_hint(s0.cend(), 100500); auto i1 = s0.insert(obj_t(1));
REQUIRE(s0 == set_t{1});
REQUIRE(i1 == std::make_pair(s0.begin(), false));
auto i2 = s0.insert(obj_t(2));
REQUIRE(s0 == set_t{1,2});
REQUIRE(i2 == std::make_pair(s0.begin() + 1, true));
s0.insert(s0.cbegin(), 1);
s0.insert(s0.cbegin(), 2);
s0.insert(s0.cend(), 1);
s0.insert(s0.cend(), 2);
REQUIRE(s0 == set_t{1,2});
s0.insert(s0.cbegin(), 0);
REQUIRE(s0 == set_t{0,1,2});
s0.insert(s0.cend(), 3);
REQUIRE(s0 == set_t{0,1,2,3});
s0.insert(s0.cbegin(), 4);
s0.insert(s0.cend(), -1);
REQUIRE(s0 == set_t{-1,0,1,2,3,4});
s0.insert(s0.cbegin() + 2, obj_t(5));
REQUIRE(s0 == set_t{-1,0,1,2,3,4,5});
s0.insert(s0.cbegin(), obj_t(-2));
REQUIRE(s0 == set_t{-2,-1,0,1,2,3,4,5});
}
{
set_t s0;
auto e0 = s0.emplace(3);
REQUIRE(s0 == set_t{3});
REQUIRE(e0 == std::make_pair(s0.begin(), true));
auto e1 = s0.emplace(obj_t(3));
REQUIRE(e1 == std::make_pair(s0.begin(), false));
auto e2 = s0.emplace(4);
REQUIRE(s0 == set_t{3,4});
REQUIRE(e2 == std::make_pair(s0.begin() + 1, true));
auto e3 = s0.emplace_hint(s0.cbegin(), 1);
REQUIRE(e3 == s0.begin());
auto e4 = s0.emplace_hint(s0.cend(), 2);
REQUIRE(e4 == s0.begin() + 1);
s0.emplace_hint(s0.cbegin(), 5);
s0.emplace_hint(s0.cend(), 6);
REQUIRE(s0 == set_t{1,2,3,4,5,6});
} }
} }
SECTION("erasers") { SECTION("erasers") {
using set_t = flat_set<int>; using set_t = flat_set<int>;
set_t s0; {
s0.clear(); set_t s0{1,2,3,4,5};
s0.erase(s0.begin()); s0.clear();
s0.erase(s0.cbegin()); REQUIRE(s0.empty());
s0.erase(s0.begin(), s0.end()); }
s0.erase(s0.cbegin(), s0.cend()); {
s0.erase(42); set_t s0{1,2,3,4,5};
set_t s1; auto i = s0.erase(s0.find(3));
s0.swap(s1); REQUIRE(i == s0.begin() + 2);
swap(s0, s1); REQUIRE(s0 == set_t{1,2,4,5});
}
{
set_t s0{1,2,3,4,5};
auto i = s0.erase(s0.begin() + 2, s0.end());
REQUIRE(i == s0.end());
REQUIRE(s0 == set_t{1,2});
}
{
set_t s0{1,2,3,4,5};
REQUIRE(s0.erase(2) == 1);
REQUIRE(s0.erase(6) == 0);
REQUIRE(s0 == set_t{1,3,4,5});
}
{
set_t s0{1,2,3};
set_t s1{3,4,5};
s0.swap(s1);
REQUIRE(s0 == set_t{3,4,5});
REQUIRE(s1 == set_t{1,2,3});
swap(s1, s0);
REQUIRE(s0 == set_t{1,2,3});
REQUIRE(s1 == set_t{3,4,5});
}
} }
SECTION("lookup") { SECTION("lookup") {
using set_t = flat_set<int>; using set_t = flat_set<int>;
set_t s0; {
s0.count(10); set_t s0{1,2,3,4,5};
s0.find(10); REQUIRE(s0.count(3));
my_as_const(s0).find(10); REQUIRE_FALSE(s0.count(6));
s0.equal_range(20); REQUIRE(my_as_const(s0).count(5));
my_as_const(s0).equal_range(20); REQUIRE_FALSE(my_as_const(s0).count(0));
s0.lower_bound(30); }
my_as_const(s0).lower_bound(30); {
s0.upper_bound(30); set_t s0{1,2,3,4,5};
my_as_const(s0).upper_bound(30); REQUIRE(s0.find(2) == s0.begin() + 1);
REQUIRE(my_as_const(s0).find(3) == s0.cbegin() + 2);
REQUIRE(s0.find(6) == s0.end());
REQUIRE(my_as_const(s0).find(0) == s0.cend());
}
{
set_t s0{1,2,3,4,5};
REQUIRE(s0.equal_range(3) == std::make_pair(s0.begin() + 2, s0.begin() + 3));
REQUIRE(s0.equal_range(6) == std::make_pair(s0.end(), s0.end()));
REQUIRE(my_as_const(s0).equal_range(3) == std::make_pair(s0.cbegin() + 2, s0.cbegin() + 3));
REQUIRE(my_as_const(s0).equal_range(0) == std::make_pair(s0.cbegin(), s0.cbegin()));
}
{
set_t s0{0,3,6,9};
REQUIRE(s0.lower_bound(0) == s0.begin());
REQUIRE(s0.lower_bound(1) == s0.begin() + 1);
REQUIRE(s0.lower_bound(10) == s0.end());
REQUIRE(my_as_const(s0).lower_bound(-1) == s0.cbegin());
REQUIRE(my_as_const(s0).lower_bound(7) == s0.cbegin() + 3);
}
} }
SECTION("observers") { SECTION("observers") {
using set_t = flat_set<int>; struct my_less {
set_t s0; int i;
my_as_const(s0).key_comp(); my_less(int i) : i(i) {}
my_as_const(s0).value_comp(); bool operator()(int l, int r) const {
return l < r;
}
};
using set_t = flat_set<int, my_less>;
set_t s0(my_less(42));
REQUIRE(my_as_const(s0).key_comp().i == 42);
REQUIRE(my_as_const(s0).value_comp().i == 42);
} }
SECTION("operators") { SECTION("operators") {
using set_t = flat_set<int>; using set_t = flat_set<int>;
set_t s0;
set_t s1; REQUIRE(set_t{1,2,3} == set_t{3,2,1});
REQUIRE(s0 == s1); REQUIRE_FALSE(set_t{1,2,3} == set_t{3,2,4});
REQUIRE_FALSE(s0 != s1); REQUIRE_FALSE(set_t{1,2,3} == set_t{1,2,3,4});
REQUIRE_FALSE(s0 < s1);
REQUIRE_FALSE(s0 > s1); REQUIRE(set_t{1,2,3} != set_t{3,2,4});
REQUIRE(s0 <= s1); REQUIRE_FALSE(set_t{1,2,3} != set_t{3,2,1});
REQUIRE(s0 >= s1);
REQUIRE(set_t{2,3,4,6} < set_t{2,3,5});
REQUIRE(set_t{2,3,4,6} <= set_t{2,3,5});
REQUIRE_FALSE(set_t{2,3,5} < set_t{2,3,4,6});
REQUIRE_FALSE(set_t{2,3,5} <= set_t{2,3,4,6});
REQUIRE_FALSE(set_t{2,3,4,6} > set_t{2,3,5});
REQUIRE_FALSE(set_t{2,3,4,6} >= set_t{2,3,5});
REQUIRE(set_t{2,3,5} > set_t{2,3,4,6});
REQUIRE(set_t{2,3,5} >= set_t{2,3,4,6});
REQUIRE_FALSE(set_t{1,2,3} < set_t{1,2,3});
REQUIRE(set_t{1,2,3} <= set_t{1,2,3});
REQUIRE_FALSE(set_t{1,2,3} > set_t{1,2,3});
REQUIRE(set_t{1,2,3} >= set_t{1,2,3});
} }
} }