diff --git a/flat_map.hpp b/flat_map.hpp index 67b6ace..952d391 100644 --- a/flat_map.hpp +++ b/flat_map.hpp @@ -133,6 +133,33 @@ namespace flat_hpp insert(ilist); } + flat_map(flat_map&& other) + : data_(std::move(other.data_)) + , compare_(std::move(other.compare_)) {} + + flat_map(const flat_map& other) + : data_(other.data_) + , compare_(other.compare_) {} + + flat_map& operator=(flat_map&& other) { + if ( this != &other ) { + flat_map(std::move(other)).swap(*this); + } + return *this; + } + + flat_map& operator=(const flat_map& other) { + if ( this != &other ) { + flat_map(other).swap(*this); + } + return *this; + } + + flat_map& operator=(std::initializer_list ilist) { + flat_map(ilist).swap(*this); + return *this; + } + allocator_type get_allocator() const { return data_.get_allocator(); } @@ -166,15 +193,21 @@ namespace flat_hpp } mapped_type& operator[](key_type&& key) { - return insert(value_type(std::move(key), mapped_type())).first->second; + const iterator iter = find(key); + return iter != end() + ? iter->second + : emplace(std::move(key), mapped_type()).first->second; } mapped_type& operator[](const key_type& key) { - return insert(value_type(key, mapped_type())).first->second; + const iterator iter = find(key); + return iter != end() + ? iter->second + : emplace(key, mapped_type()).first->second; } mapped_type& at(const key_type& key) { - const auto iter = find(key); + const iterator iter = find(key); if ( iter != end() ) { return iter->second; } @@ -182,13 +215,20 @@ namespace flat_hpp } const mapped_type& at(const key_type& key) const { - const auto iter = find(key); + const const_iterator iter = find(key); if ( iter != end() ) { return iter->second; } throw std::out_of_range("flat_map::at: key not found"); } + std::pair insert(value_type&& value) { + const iterator iter = lower_bound(value.first); + return iter == end() || compare_(value.first, iter->first) + ? std::make_pair(data_.insert(iter, std::move(value)), true) + : std::make_pair(iter, false); + } + std::pair insert(const value_type& value) { const iterator iter = lower_bound(value.first); return iter == end() || compare_(value.first, iter->first) @@ -196,13 +236,20 @@ namespace flat_hpp : std::make_pair(iter, false); } - iterator insert(const_iterator hint, const value_type& value) { + iterator insert(const_iterator hint, value_type&& value) { return (hint == begin() || compare_((hint - 1)->first, value.first)) && (hint == end() || compare_(value.first, hint->first)) ? 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)->first, value.first)) + && (hint == end() || compare_(value.first, hint->first)) + ? data_.insert(hint, value) + : insert(value).first; + } + template < typename InputIter > void insert(InputIter first, InputIter last) { while ( first != last ) { diff --git a/flat_map_tests.cpp b/flat_map_tests.cpp index 40891f6..cdacde3 100644 --- a/flat_map_tests.cpp +++ b/flat_map_tests.cpp @@ -145,6 +145,32 @@ TEST_CASE("flat_map") { REQUIRE(s0.get_allocator().i == 0); REQUIRE(s1.get_allocator().i == 42); } + + { + auto s0 = map_t{{0,1}, {1,2}}; + auto s1 = s0; + REQUIRE(s0 == map_t{{0,1}, {1,2}}); + REQUIRE(s1 == map_t{{0,1}, {1,2}}); + auto s2 = std::move(s1); + REQUIRE(s1.empty()); + REQUIRE(s2 == map_t{{0,1}, {1,2}}); + } + + { + auto s0 = map_t{{0,1}, {1,2}}; + map_t s1; + s1 = s0; + REQUIRE(s0 == map_t{{0,1}, {1,2}}); + REQUIRE(s1 == map_t{{0,1}, {1,2}}); + map_t s2; + s2 = std::move(s1); + REQUIRE(s0 == map_t{{0,1}, {1,2}}); + REQUIRE(s1.empty()); + REQUIRE(s2 == map_t{{0,1}, {1,2}}); + map_t s3; + s3 = {{0,1}, {1,2}}; + REQUIRE(s3 == map_t{{0,1}, {1,2}}); + } } SECTION("capacity") { using map_t = flat_map; @@ -173,15 +199,34 @@ TEST_CASE("flat_map") { REQUIRE(s0.max_size() == std::allocator>().max_size()); } SECTION("access") { - using map_t = flat_map; + struct obj_t { + obj_t(int i) : i(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 map_t = flat_map; map_t s0; - s0[1] = 42; + + obj_t k1(1); + + s0[k1] = 42; + REQUIRE(s0[k1] == 42); REQUIRE(s0 == map_t{{1,42}}); + s0[1] = 84; + REQUIRE(s0[1] == 84); REQUIRE(s0 == map_t{{1,84}}); REQUIRE(s0.at(1) == 84); - REQUIRE(my_as_const(s0).at(1) == 84); + REQUIRE(my_as_const(s0).at(k1) == 84); REQUIRE_THROWS_AS(s0.at(0), std::out_of_range); REQUIRE_THROWS_AS(my_as_const(s0).at(0), std::out_of_range); } @@ -199,12 +244,15 @@ TEST_CASE("flat_map") { } }; - using map_t = flat_map; + using map_t = flat_map; { map_t s0; - auto i0 = s0.insert(std::make_pair(1, 42)); + auto k1_42 = std::make_pair(1, 42); + auto k3_84 = std::make_pair(3, 84); + + auto i0 = s0.insert(k1_42); REQUIRE(s0 == map_t{{1,42}}); REQUIRE(i0 == std::make_pair(s0.begin(), true)); @@ -216,7 +264,7 @@ TEST_CASE("flat_map") { REQUIRE(s0 == map_t{{1,42},{2,42}}); REQUIRE(i2 == std::make_pair(s0.begin() + 1, true)); - auto i3 = s0.insert(s0.cend(), std::make_pair(3, 84)); + auto i3 = s0.insert(s0.cend(), k3_84); REQUIRE(i3 == s0.begin() + 2); s0.insert(s0.cend(), std::make_pair(4, obj_t(84))); diff --git a/flat_set.hpp b/flat_set.hpp index 12cfa69..a63e51e 100644 --- a/flat_set.hpp +++ b/flat_set.hpp @@ -111,6 +111,33 @@ namespace flat_hpp insert(ilist); } + flat_set(flat_set&& other) + : data_(std::move(other.data_)) + , compare_(std::move(other.compare_)) {} + + flat_set(const flat_set& other) + : data_(other.data_) + , compare_(other.compare_) {} + + flat_set& operator=(flat_set&& other) { + if ( this != &other ) { + flat_set(std::move(other)).swap(*this); + } + return *this; + } + + flat_set& operator=(const flat_set& other) { + if ( this != &other ) { + flat_set(other).swap(*this); + } + return *this; + } + + flat_set& operator=(std::initializer_list ilist) { + flat_set(ilist).swap(*this); + return *this; + } + allocator_type get_allocator() const { return data_.get_allocator(); } diff --git a/flat_set_tests.cpp b/flat_set_tests.cpp index 92c9383..5331c3c 100644 --- a/flat_set_tests.cpp +++ b/flat_set_tests.cpp @@ -129,6 +129,32 @@ TEST_CASE("flat_set") { REQUIRE(s0.get_allocator().i == 0); REQUIRE(s1.get_allocator().i == 42); } + + { + auto s0 = set_t{0,1,2}; + auto s1 = s0; + REQUIRE(s0 == set_t{0,1,2}); + REQUIRE(s1 == set_t{0,1,2}); + auto s2 = std::move(s1); + REQUIRE(s1.empty()); + REQUIRE(s2 == set_t{0,1,2}); + } + + { + auto s0 = set_t{0,1,2}; + set_t s1; + s1 = s0; + REQUIRE(s0 == set_t{0,1,2}); + REQUIRE(s1 == set_t{0,1,2}); + set_t s2; + s2 = std::move(s1); + REQUIRE(s0 == set_t{0,1,2}); + REQUIRE(s1.empty()); + REQUIRE(s2 == set_t{0,1,2}); + set_t s3; + s3 = {1,2,3}; + REQUIRE(s3 == set_t{1,2,3}); + } } SECTION("capacity") { using set_t = flat_set;