add optional capacity control functions #3

This commit is contained in:
2019-05-05 09:03:32 +07:00
parent 65963bc670
commit a5ecda71bb
5 changed files with 265 additions and 60 deletions

View File

@@ -132,6 +132,9 @@ const_reverse_iterator crend() const noexcept;
bool empty() const noexcept; bool empty() const noexcept;
size_type size() const noexcept; size_type size() const noexcept;
size_type max_size() const noexcept; size_type max_size() const noexcept;
size_type capacity() const noexcept;
void reserve(size_type ncapacity);
void shrink_to_fit();
``` ```
### Modifiers ### Modifiers
@@ -330,6 +333,9 @@ const_reverse_iterator crend() const noexcept;
bool empty() const noexcept; bool empty() const noexcept;
size_type size() const noexcept; size_type size() const noexcept;
size_type max_size() const noexcept; size_type max_size() const noexcept;
size_type capacity() const noexcept;
void reserve(size_type ncapacity);
void shrink_to_fit();
``` ```
### Element access ### Element access

View File

@@ -192,6 +192,18 @@ namespace flat_hpp
return data_.max_size(); return data_.max_size();
} }
size_type capacity() const noexcept {
return data_.capacity();
}
void reserve(size_type ncapacity) {
data_.reserve(ncapacity);
}
void shrink_to_fit() {
data_.shrink_to_fit();
}
mapped_type& operator[](key_type&& key) { mapped_type& operator[](key_type&& key) {
const iterator iter = find(key); const iterator iter = find(key);
return iter != end() return iter != end()
@@ -354,39 +366,88 @@ namespace flat_hpp
namespace flat_hpp namespace flat_hpp
{ {
template < typename K, typename V, typename C, typename A > template < typename Key
void swap(flat_map<K, V, C, A>& l, flat_map<K, V, C, A>& r) { , typename Value
, typename Compare
, typename Allocator
, typename Container >
void swap(
flat_map<Key, Value, Compare, Allocator, Container>& l,
flat_map<Key, Value, Compare, Allocator, Container>& r)
{
l.swap(r); l.swap(r);
} }
template < typename K, typename V, typename C, typename A > template < typename Key
bool operator==(const flat_map<K, V, C, A>& l, const flat_map<K, V, C, A>& r) { , typename Value
, typename Compare
, typename Allocator
, typename Container >
bool operator==(
const flat_map<Key, Value, Compare, Allocator, Container>& l,
const flat_map<Key, Value, Compare, Allocator, Container>& r)
{
return l.size() == r.size() return l.size() == r.size()
&& std::equal(l.begin(), l.end(), r.begin(), r.end()); && std::equal(l.begin(), l.end(), r.begin(), r.end());
} }
template < typename K, typename V, typename C, typename A > template < typename Key
bool operator!=(const flat_map<K, V, C, A>& l, const flat_map<K, V, C, A>& r) { , typename Value
, typename Compare
, typename Allocator
, typename Container >
bool operator!=(
const flat_map<Key, Value, Compare, Allocator, Container>& l,
const flat_map<Key, Value, Compare, Allocator, Container>& r)
{
return !(l == r); return !(l == r);
} }
template < typename K, typename V, typename C, typename A > template < typename Key
bool operator<(const flat_map<K, V, C, A>& l, const flat_map<K, V, C, A>& r) { , typename Value
, typename Compare
, typename Allocator
, typename Container >
bool operator<(
const flat_map<Key, Value, Compare, Allocator, Container>& l,
const flat_map<Key, Value, Compare, Allocator, Container>& r)
{
return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end()); return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end());
} }
template < typename K, typename V, typename C, typename A > template < typename Key
bool operator>(const flat_map<K, V, C, A>& l, const flat_map<K, V, C, A>& r) { , typename Value
, typename Compare
, typename Allocator
, typename Container >
bool operator>(
const flat_map<Key, Value, Compare, Allocator, Container>& l,
const flat_map<Key, Value, Compare, Allocator, Container>& r)
{
return r < l; return r < l;
} }
template < typename K, typename V, typename C, typename A > template < typename Key
bool operator<=(const flat_map<K, V, C, A>& l, const flat_map<K, V, C, A>& r) { , typename Value
, typename Compare
, typename Allocator
, typename Container >
bool operator<=(
const flat_map<Key, Value, Compare, Allocator, Container>& l,
const flat_map<Key, Value, Compare, Allocator, Container>& r)
{
return !(r < l); return !(r < l);
} }
template < typename K, typename V, typename C, typename A > template < typename Key
bool operator>=(const flat_map<K, V, C, A>& l, const flat_map<K, V, C, A>& r) { , typename Value
, typename Compare
, typename Allocator
, typename Container >
bool operator>=(
const flat_map<Key, Value, Compare, Allocator, Container>& l,
const flat_map<Key, Value, Compare, Allocator, Container>& r)
{
return !(l < r); return !(l < r);
} }
} }

View File

@@ -7,6 +7,8 @@
#define CATCH_CONFIG_FAST_COMPILE #define CATCH_CONFIG_FAST_COMPILE
#include "catch.hpp" #include "catch.hpp"
#include <deque>
#include "flat_map.hpp" #include "flat_map.hpp"
using namespace flat_hpp; using namespace flat_hpp;
@@ -174,29 +176,60 @@ TEST_CASE("flat_map") {
} }
SECTION("capacity") { SECTION("capacity") {
using map_t = flat_map<int, unsigned>; using map_t = flat_map<int, unsigned>;
map_t s0;
REQUIRE(s0.empty()); {
REQUIRE_FALSE(s0.size()); map_t s0;
REQUIRE(s0.max_size() == std::allocator<std::pair<int,unsigned>>().max_size());
s0.insert({2,42}); REQUIRE(s0.empty());
REQUIRE_FALSE(s0.size());
REQUIRE(s0.max_size() == std::allocator<std::pair<int,unsigned>>().max_size());
REQUIRE_FALSE(s0.empty()); s0.insert({2,42});
REQUIRE(s0.size() == 1u);
REQUIRE(s0.max_size() == std::allocator<std::pair<int,unsigned>>().max_size());
s0.insert({2,84}); REQUIRE_FALSE(s0.empty());
REQUIRE(s0.size() == 1u); REQUIRE(s0.size() == 1u);
REQUIRE(s0.max_size() == std::allocator<std::pair<int,unsigned>>().max_size());
s0.insert({3,84}); s0.insert({2,84});
REQUIRE(s0.size() == 2u); REQUIRE(s0.size() == 1u);
s0.clear(); s0.insert({3,84});
REQUIRE(s0.size() == 2u);
REQUIRE(s0.empty()); s0.clear();
REQUIRE_FALSE(s0.size());
REQUIRE(s0.max_size() == std::allocator<std::pair<int,unsigned>>().max_size()); REQUIRE(s0.empty());
REQUIRE_FALSE(s0.size());
REQUIRE(s0.max_size() == std::allocator<std::pair<int,unsigned>>().max_size());
}
{
map_t s0;
REQUIRE(s0.capacity() == 0);
s0.reserve(42);
REQUIRE(s0.capacity() == 42);
s0.insert({{1,2},{2,3},{3,4}});
REQUIRE(s0.capacity() == 42);
s0.shrink_to_fit();
REQUIRE(s0.size() == 3);
REQUIRE(s0.capacity() == 3);
REQUIRE(s0 == map_t{{1,2},{2,3},{3,4}});
using alloc2_t = dummy_allocator<
std::pair<int, unsigned>>;
using map2_t = flat_map<
int,
unsigned,
std::less<int>,
alloc2_t,
std::deque<std::pair<int, unsigned>, alloc2_t>>;
map2_t s1;
s1.insert({{1,2},{2,3},{3,4}});
REQUIRE(s1 == map2_t{{1,2},{2,3},{3,4}});
}
} }
SECTION("access") { SECTION("access") {
struct obj_t { struct obj_t {
@@ -225,6 +258,10 @@ TEST_CASE("flat_map") {
REQUIRE(s0[1] == 84); REQUIRE(s0[1] == 84);
REQUIRE(s0 == map_t{{1,84}}); REQUIRE(s0 == map_t{{1,84}});
s0[2] = 21;
REQUIRE(s0[2] == 21);
REQUIRE(s0 == map_t{{1,84},{2,21}});
REQUIRE(s0.at(1) == 84); REQUIRE(s0.at(1) == 84);
REQUIRE(my_as_const(s0).at(k1) == 84); REQUIRE(my_as_const(s0).at(k1) == 84);
REQUIRE_THROWS_AS(s0.at(0), std::out_of_range); REQUIRE_THROWS_AS(s0.at(0), std::out_of_range);
@@ -394,5 +431,13 @@ TEST_CASE("flat_map") {
REQUIRE(map_t{{1,2},{3,4}} <= map_t{{1,2},{3,4}}); REQUIRE(map_t{{1,2},{3,4}} <= map_t{{1,2},{3,4}});
REQUIRE_FALSE(map_t{{1,2},{3,4}} > map_t{{1,2},{3,4}}); REQUIRE_FALSE(map_t{{1,2},{3,4}} > map_t{{1,2},{3,4}});
REQUIRE(map_t{{1,2},{3,4}} >= map_t{{1,2},{3,4}}); REQUIRE(map_t{{1,2},{3,4}} >= map_t{{1,2},{3,4}});
const map_t s0;
REQUIRE(s0 == s0);
REQUIRE_FALSE(s0 != s0);
REQUIRE_FALSE(s0 < s0);
REQUIRE_FALSE(s0 > s0);
REQUIRE(s0 <= s0);
REQUIRE(s0 >= s0);
} }
} }

View File

@@ -170,6 +170,18 @@ namespace flat_hpp
return data_.max_size(); return data_.max_size();
} }
size_type capacity() const noexcept {
return data_.capacity();
}
void reserve(size_type ncapacity) {
data_.reserve(ncapacity);
}
void shrink_to_fit() {
data_.shrink_to_fit();
}
std::pair<iterator, bool> insert(value_type&& value) { std::pair<iterator, bool> insert(value_type&& value) {
const iterator iter = lower_bound(value); const iterator iter = lower_bound(value);
return iter == end() || compare_(value, *iter) return iter == end() || compare_(value, *iter)
@@ -302,39 +314,81 @@ namespace flat_hpp
namespace flat_hpp namespace flat_hpp
{ {
template < typename K, typename C, typename A > template < typename Key
void swap(flat_set<K, C, A>& l, flat_set<K, C, A>& r) { , typename Compare
, typename Allocator
, typename Container >
void swap(
flat_set<Key, Compare, Allocator, Container>& l,
flat_set<Key, Compare, Allocator, Container>& r)
{
l.swap(r); l.swap(r);
} }
template < typename K, typename C, typename A > template < typename Key
bool operator==(const flat_set<K, C, A>& l, const flat_set<K, C, A>& r) { , typename Compare
, typename Allocator
, typename Container >
bool operator==(
const flat_set<Key, Compare, Allocator, Container>& l,
const flat_set<Key, Compare, Allocator, Container>& r)
{
return l.size() == r.size() return l.size() == r.size()
&& std::equal(l.begin(), l.end(), r.begin(), r.end()); && std::equal(l.begin(), l.end(), r.begin(), r.end());
} }
template < typename K, typename C, typename A > template < typename Key
bool operator!=(const flat_set<K, C, A>& l, const flat_set<K, C, A>& r) { , typename Compare
, typename Allocator
, typename Container >
bool operator!=(
const flat_set<Key, Compare, Allocator, Container>& l,
const flat_set<Key, Compare, Allocator, Container>& r)
{
return !(l == r); return !(l == r);
} }
template < typename K, typename C, typename A > template < typename Key
bool operator<(const flat_set<K, C, A>& l, const flat_set<K, C, A>& r) { , typename Compare
, typename Allocator
, typename Container >
bool operator<(
const flat_set<Key, Compare, Allocator, Container>& l,
const flat_set<Key, Compare, Allocator, Container>& r)
{
return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end()); return std::lexicographical_compare(l.begin(), l.end(), r.begin(), r.end());
} }
template < typename K, typename C, typename A > template < typename Key
bool operator>(const flat_set<K, C, A>& l, const flat_set<K, C, A>& r) { , typename Compare
, typename Allocator
, typename Container >
bool operator>(
const flat_set<Key, Compare, Allocator, Container>& l,
const flat_set<Key, Compare, Allocator, Container>& r)
{
return r < l; return r < l;
} }
template < typename K, typename C, typename A > template < typename Key
bool operator<=(const flat_set<K, C, A>& l, const flat_set<K, C, A>& r) { , typename Compare
, typename Allocator
, typename Container >
bool operator<=(
const flat_set<Key, Compare, Allocator, Container>& l,
const flat_set<Key, Compare, Allocator, Container>& r)
{
return !(r < l); return !(r < l);
} }
template < typename K, typename C, typename A > template < typename Key
bool operator>=(const flat_set<K, C, A>& l, const flat_set<K, C, A>& r) { , typename Compare
, typename Allocator
, typename Container >
bool operator>=(
const flat_set<Key, Compare, Allocator, Container>& l,
const flat_set<Key, Compare, Allocator, Container>& r)
{
return !(l < r); return !(l < r);
} }
} }

View File

@@ -7,6 +7,8 @@
#define CATCH_CONFIG_FAST_COMPILE #define CATCH_CONFIG_FAST_COMPILE
#include "catch.hpp" #include "catch.hpp"
#include <deque>
#include "flat_set.hpp" #include "flat_set.hpp"
using namespace flat_hpp; using namespace flat_hpp;
@@ -158,29 +160,58 @@ TEST_CASE("flat_set") {
} }
SECTION("capacity") { SECTION("capacity") {
using set_t = flat_set<int>; using set_t = flat_set<int>;
set_t s0;
REQUIRE(s0.empty()); {
REQUIRE_FALSE(s0.size()); set_t s0;
REQUIRE(s0.max_size() == std::allocator<int>().max_size());
s0.insert(42); REQUIRE(s0.empty());
REQUIRE_FALSE(s0.size());
REQUIRE(s0.max_size() == std::allocator<int>().max_size());
REQUIRE_FALSE(s0.empty()); s0.insert(42);
REQUIRE(s0.size() == 1u);
REQUIRE(s0.max_size() == std::allocator<int>().max_size());
s0.insert(42); REQUIRE_FALSE(s0.empty());
REQUIRE(s0.size() == 1u); REQUIRE(s0.size() == 1u);
REQUIRE(s0.max_size() == std::allocator<int>().max_size());
s0.insert(84); s0.insert(42);
REQUIRE(s0.size() == 2u); REQUIRE(s0.size() == 1u);
s0.clear(); s0.insert(84);
REQUIRE(s0.size() == 2u);
REQUIRE(s0.empty()); s0.clear();
REQUIRE_FALSE(s0.size());
REQUIRE(s0.max_size() == std::allocator<int>().max_size()); REQUIRE(s0.empty());
REQUIRE_FALSE(s0.size());
REQUIRE(s0.max_size() == std::allocator<int>().max_size());
}
{
set_t s0;
REQUIRE(s0.capacity() == 0);
s0.reserve(42);
REQUIRE(s0.capacity() == 42);
s0.insert({1,2,3});
REQUIRE(s0.capacity() == 42);
s0.shrink_to_fit();
REQUIRE(s0.size() == 3);
REQUIRE(s0.capacity() == 3);
REQUIRE(s0 == set_t{1,2,3});
using alloc2_t = dummy_allocator<int>;
using set2_t = flat_set<
int,
std::less<int>,
alloc2_t,
std::deque<int, alloc2_t>>;
set2_t s1;
s1.insert({1,2,3});
REQUIRE(s1 == set2_t{1,2,3});
}
} }
SECTION("inserts") { SECTION("inserts") {
struct obj_t { struct obj_t {
@@ -365,5 +396,13 @@ TEST_CASE("flat_set") {
REQUIRE(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_FALSE(set_t{1,2,3} > set_t{1,2,3});
REQUIRE(set_t{1,2,3} >= set_t{1,2,3}); REQUIRE(set_t{1,2,3} >= set_t{1,2,3});
const set_t s0;
REQUIRE(s0 == s0);
REQUIRE_FALSE(s0 != s0);
REQUIRE_FALSE(s0 < s0);
REQUIRE_FALSE(s0 > s0);
REQUIRE(s0 <= s0);
REQUIRE(s0 >= s0);
} }
} }