Make Map<> copyable.

pull/20044/head
Mark D. Roth 5 years ago
parent 4a862cb28c
commit 5d646ff9ff
  1. 71
      src/core/lib/gprpp/map.h
  2. 29
      test/core/gprpp/map_test.cc

@ -63,6 +63,7 @@ class Map {
typedef Pair<key_type, mapped_type> value_type;
typedef Compare key_compare;
class iterator;
class const_iterator;
Map() = default;
~Map() { clear(); }
@ -83,6 +84,22 @@ class Map {
return *this;
}
// Copyable.
Map(const Map& other) {
for (const auto& p : other) {
emplace(p);
}
}
Map& operator=(const Map& other) {
if (this != &other) {
clear();
for (const auto& p : other) {
emplace(p);
}
}
return *this;
}
T& operator[](key_type&& key);
T& operator[](const key_type& key);
iterator find(const key_type& k);
@ -117,6 +134,13 @@ class Map {
iterator end() { return iterator(this, nullptr); }
const_iterator begin() const {
Entry* curr = GetMinEntry(root_);
return const_iterator(this, curr);
}
const_iterator end() const { return const_iterator(this, nullptr); }
iterator lower_bound(const Key& k) {
// This is a workaround for "const key_compare compare;"
// because some versions of compilers cannot build this by requiring
@ -209,6 +233,53 @@ class Map<Key, T, Compare>::iterator
GrpcMap* map_;
};
template <class Key, class T, class Compare>
class Map<Key, T, Compare>::const_iterator
: public std::iterator<std::input_iterator_tag, Pair<Key, T>, int32_t,
Pair<Key, T>*, Pair<Key, T>&> {
public:
const_iterator(const const_iterator& iter)
: curr_(iter.curr_), map_(iter.map_) {}
bool operator==(const const_iterator& rhs) const {
return (curr_ == rhs.curr_);
}
bool operator!=(const const_iterator& rhs) const {
return (curr_ != rhs.curr_);
}
const_iterator& operator++() {
curr_ = map_->InOrderSuccessor(curr_);
return *this;
}
const_iterator operator++(int) {
Entry* prev = curr_;
curr_ = map_->InOrderSuccessor(curr_);
return const_iterator(map_, prev);
}
const_iterator& operator=(const const_iterator& other) {
if (this != &other) {
this->curr_ = other.curr_;
this->map_ = other.map_;
}
return *this;
}
// operator*()
const value_type& operator*() const { return curr_->pair; }
// operator->()
const value_type* operator->() const { return &curr_->pair; }
private:
friend class Map<key_type, mapped_type, key_compare>;
using GrpcMap = typename ::grpc_core::Map<Key, T, Compare>;
const_iterator(const GrpcMap* map, Entry* curr) : curr_(curr), map_(map) {}
Entry* curr_;
const GrpcMap* map_;
};
template <class Key, class T, class Compare>
T& Map<Key, T, Compare>::operator[](key_type&& key) {
auto iter = find(key);

@ -466,6 +466,35 @@ TEST_F(MapTest, MoveAssignment) {
EXPECT_EQ(test_map2.end(), test_map2.find("xxx"));
}
// Test copy ctor
TEST_F(MapTest, CopyCtor) {
Map<const char*, Payload, StringLess> test_map;
for (int i = 0; i < 5; i++) {
test_map.emplace(kKeys[i], Payload(i));
}
Map<const char*, Payload, StringLess> test_map2 = test_map;
for (int i = 0; i < 5; i++) {
EXPECT_EQ(i, test_map.find(kKeys[i])->second.data());
EXPECT_EQ(i, test_map2.find(kKeys[i])->second.data());
}
}
// Test copy assignment
TEST_F(MapTest, CopyAssignment) {
Map<const char*, Payload, StringLess> test_map;
for (int i = 0; i < 5; i++) {
test_map.emplace(kKeys[i], Payload(i));
}
Map<const char*, Payload, StringLess> test_map2;
test_map2.emplace("xxx", Payload(123));
test_map2 = test_map;
for (int i = 0; i < 5; i++) {
EXPECT_EQ(i, test_map.find(kKeys[i])->second.data());
EXPECT_EQ(i, test_map2.find(kKeys[i])->second.data());
}
EXPECT_EQ(test_map2.end(), test_map2.find("xxx"));
}
} // namespace testing
} // namespace grpc_core

Loading…
Cancel
Save