Commit 94a77ab3 authored by James Gill's avatar James Gill Committed by Facebook Github Bot

Implement c++20 contains method on F14Map and F14Set

Summary:
contains() is part of the c++20 spec.  This implements it, and
refactors count() to use contains().

Reviewed By: nbronson

Differential Revision: D14426805

fbshipit-source-id: 2435124e9c0a8eeb4e53109f0ddac884c227c781
parent e57833b0
...@@ -748,13 +748,13 @@ class F14BasicMap { ...@@ -748,13 +748,13 @@ class F14BasicMap {
} }
FOLLY_ALWAYS_INLINE size_type count(key_type const& key) const { FOLLY_ALWAYS_INLINE size_type count(key_type const& key) const {
return table_.find(key).atEnd() ? 0 : 1; return contains(key) ? 1 : 0;
} }
template <typename K> template <typename K>
FOLLY_ALWAYS_INLINE EnableHeterogeneousFind<K, size_type> count( FOLLY_ALWAYS_INLINE EnableHeterogeneousFind<K, size_type> count(
K const& key) const { K const& key) const {
return table_.find(key).atEnd() ? 0 : 1; return contains(key) ? 1 : 0;
} }
// prehash(key) does the work of evaluating hash_function()(key) // prehash(key) does the work of evaluating hash_function()(key)
...@@ -823,6 +823,16 @@ class F14BasicMap { ...@@ -823,6 +823,16 @@ class F14BasicMap {
return table_.makeConstIter(table_.find(token, key)); return table_.makeConstIter(table_.find(token, key));
} }
FOLLY_ALWAYS_INLINE bool contains(key_type const& key) const {
return !table_.find(key).atEnd();
}
template <typename K>
FOLLY_ALWAYS_INLINE EnableHeterogeneousFind<K, bool> contains(
K const& key) const {
return !table_.find(key).atEnd();
}
std::pair<iterator, iterator> equal_range(key_type const& key) { std::pair<iterator, iterator> equal_range(key_type const& key) {
return equal_range(*this, key); return equal_range(*this, key);
} }
......
...@@ -530,13 +530,13 @@ class F14BasicSet { ...@@ -530,13 +530,13 @@ class F14BasicSet {
//// PUBLIC - Lookup //// PUBLIC - Lookup
FOLLY_ALWAYS_INLINE size_type count(key_type const& key) const { FOLLY_ALWAYS_INLINE size_type count(key_type const& key) const {
return table_.find(key).atEnd() ? 0 : 1; return contains(key) ? 1 : 0;
} }
template <typename K> template <typename K>
FOLLY_ALWAYS_INLINE EnableHeterogeneousFind<K, size_type> count( FOLLY_ALWAYS_INLINE EnableHeterogeneousFind<K, size_type> count(
K const& key) const { K const& key) const {
return table_.find(key).atEnd() ? 0 : 1; return contains(key) ? 1 : 0;
} }
// prehash(key) does the work of evaluating hash_function()(key) // prehash(key) does the work of evaluating hash_function()(key)
...@@ -605,6 +605,16 @@ class F14BasicSet { ...@@ -605,6 +605,16 @@ class F14BasicSet {
return table_.makeIter(table_.find(token, key)); return table_.makeIter(table_.find(token, key));
} }
FOLLY_ALWAYS_INLINE bool contains(key_type const& key) const {
return !table_.find(key).atEnd();
}
template <typename K>
FOLLY_ALWAYS_INLINE EnableHeterogeneousFind<K, bool> contains(
K const& key) const {
return !table_.find(key).atEnd();
}
std::pair<iterator, iterator> equal_range(key_type const& key) { std::pair<iterator, iterator> equal_range(key_type const& key) {
return equal_range(*this, key); return equal_range(*this, key);
} }
......
...@@ -277,6 +277,8 @@ void runSimple() { ...@@ -277,6 +277,8 @@ void runSimple() {
EXPECT_EQ(h8.size(), 2); EXPECT_EQ(h8.size(), 2);
EXPECT_EQ(h8.count(s("abc")), 1); EXPECT_EQ(h8.count(s("abc")), 1);
EXPECT_EQ(h8.count(s("xyz")), 0); EXPECT_EQ(h8.count(s("xyz")), 0);
EXPECT_TRUE(h8.contains(s("abc")));
EXPECT_FALSE(h8.contains(s("xyz")));
EXPECT_TRUE(h7 != h8); EXPECT_TRUE(h7 != h8);
EXPECT_TRUE(h8 != h9); EXPECT_TRUE(h8 != h9);
...@@ -294,6 +296,10 @@ void runSimple() { ...@@ -294,6 +296,10 @@ void runSimple() {
EXPECT_EQ(h5.count(k), 1); EXPECT_EQ(h5.count(k), 1);
EXPECT_EQ(h6.count(k), 1); EXPECT_EQ(h6.count(k), 1);
EXPECT_EQ(h8.count(k), 1); EXPECT_EQ(h8.count(k), 1);
EXPECT_TRUE(h4.contains(k));
EXPECT_TRUE(h5.contains(k));
EXPECT_TRUE(h6.contains(k));
EXPECT_TRUE(h8.contains(k));
} }
EXPECT_TRUE(h2 == h7); EXPECT_TRUE(h2 == h7);
...@@ -485,6 +491,8 @@ void runRandom() { ...@@ -485,6 +491,8 @@ void runRandom() {
EXPECT_EQ(t->second.val_, r->second.val_); EXPECT_EQ(t->second.val_, r->second.val_);
} }
EXPECT_EQ(t0.count(k), r0.count(k)); EXPECT_EQ(t0.count(k), r0.count(k));
// TODO: When std::unordered_map supports c++20:
// EXPECT_EQ(t0.contains(k), r0.contains(k));
} else if (pct < 60) { } else if (pct < 60) {
// equal_range // equal_range
auto t = t0.equal_range(k); auto t = t0.equal_range(k);
...@@ -1183,10 +1191,13 @@ void runInsertAndEmplace(std::string const& name) { ...@@ -1183,10 +1191,13 @@ void runInsertAndEmplace(std::string const& name) {
M m; M m;
typename M::key_type k; typename M::key_type k;
EXPECT_EQ(m.count(k), 0); EXPECT_EQ(m.count(k), 0);
EXPECT_FALSE(m.contains(k));
m.emplace(); m.emplace();
EXPECT_EQ(m.count(k), 1); EXPECT_EQ(m.count(k), 1);
EXPECT_TRUE(m.contains(k));
m.emplace(); m.emplace();
EXPECT_EQ(m.count(k), 1); EXPECT_EQ(m.count(k), 1);
EXPECT_TRUE(m.contains(k));
} }
TEST(F14ValueMap, destructuring) { TEST(F14ValueMap, destructuring) {
...@@ -1308,6 +1319,10 @@ TEST(F14ValueMap, heterogeneousLookup) { ...@@ -1308,6 +1319,10 @@ TEST(F14ValueMap, heterogeneousLookup) {
EXPECT_TRUE(ref.end() == ref.find(ref.prehash(buddy), buddy)); EXPECT_TRUE(ref.end() == ref.find(ref.prehash(buddy), buddy));
EXPECT_EQ(hello, ref.find(ref.prehash(hello), hello)->first); EXPECT_EQ(hello, ref.find(ref.prehash(hello), hello)->first);
// contains
EXPECT_FALSE(ref.contains(buddy));
EXPECT_TRUE(ref.contains(hello));
// equal_range // equal_range
EXPECT_TRUE(std::make_pair(ref.end(), ref.end()) == ref.equal_range(buddy)); EXPECT_TRUE(std::make_pair(ref.end(), ref.end()) == ref.equal_range(buddy));
EXPECT_TRUE( EXPECT_TRUE(
...@@ -1403,6 +1418,7 @@ void runHeterogeneousInsertTest() { ...@@ -1403,6 +1418,7 @@ void runHeterogeneousInsertTest() {
resetTracking(); resetTracking();
EXPECT_EQ(map.count(10), 0); EXPECT_EQ(map.count(10), 0);
EXPECT_FALSE(map.contains(10));
EXPECT_EQ(Tracked<1>::counts.dist(Counts{0, 0, 0, 0}), 0) EXPECT_EQ(Tracked<1>::counts.dist(Counts{0, 0, 0, 0}), 0)
<< Tracked<1>::counts; << Tracked<1>::counts;
......
...@@ -269,6 +269,8 @@ void runSimple() { ...@@ -269,6 +269,8 @@ void runSimple() {
EXPECT_EQ(h8.size(), 2); EXPECT_EQ(h8.size(), 2);
EXPECT_EQ(h8.count(s("abc")), 1); EXPECT_EQ(h8.count(s("abc")), 1);
EXPECT_EQ(h8.count(s("xyz")), 0); EXPECT_EQ(h8.count(s("xyz")), 0);
EXPECT_TRUE(h8.contains(s("abc")));
EXPECT_FALSE(h8.contains(s("xyz")));
EXPECT_TRUE(h7 != h8); EXPECT_TRUE(h7 != h8);
EXPECT_TRUE(h8 != h9); EXPECT_TRUE(h8 != h9);
...@@ -286,6 +288,10 @@ void runSimple() { ...@@ -286,6 +288,10 @@ void runSimple() {
EXPECT_EQ(h5.count(k), 1); EXPECT_EQ(h5.count(k), 1);
EXPECT_EQ(h6.count(k), 1); EXPECT_EQ(h6.count(k), 1);
EXPECT_EQ(h8.count(k), 1); EXPECT_EQ(h8.count(k), 1);
EXPECT_TRUE(h4.contains(k));
EXPECT_TRUE(h5.contains(k));
EXPECT_TRUE(h6.contains(k));
EXPECT_TRUE(h8.contains(k));
} }
h8.clear(); h8.clear();
...@@ -439,6 +445,8 @@ void runRandom() { ...@@ -439,6 +445,8 @@ void runRandom() {
EXPECT_EQ(*t, *r); EXPECT_EQ(*t, *r);
} }
EXPECT_EQ(t0.count(k), r0.count(k)); EXPECT_EQ(t0.count(k), r0.count(k));
// TODO: When std::unordered_set supports c++20:
// EXPECT_EQ(t0.contains(k), r0.contains(k));
} else if (pct < 60) { } else if (pct < 60) {
// equal_range // equal_range
auto t = t0.equal_range(k); auto t = t0.equal_range(k);
...@@ -829,10 +837,13 @@ void runInsertAndEmplace() { ...@@ -829,10 +837,13 @@ void runInsertAndEmplace() {
S s; S s;
typename S::value_type k; typename S::value_type k;
EXPECT_EQ(s.count(k), 0); EXPECT_EQ(s.count(k), 0);
EXPECT_FALSE(s.contains(k));
s.emplace(); s.emplace();
EXPECT_EQ(s.count(k), 1); EXPECT_EQ(s.count(k), 1);
EXPECT_TRUE(s.contains(k));
s.emplace(); s.emplace();
EXPECT_EQ(s.count(k), 1); EXPECT_EQ(s.count(k), 1);
EXPECT_TRUE(s.contains(k));
} }
TEST(F14ValueSet, destructuring) { TEST(F14ValueSet, destructuring) {
...@@ -982,6 +993,10 @@ TEST(F14ValueSet, heterogeneous) { ...@@ -982,6 +993,10 @@ TEST(F14ValueSet, heterogeneous) {
EXPECT_TRUE(ref.end() == ref.find(ref.prehash(buddy), buddy)); EXPECT_TRUE(ref.end() == ref.find(ref.prehash(buddy), buddy));
EXPECT_EQ(hello, *ref.find(ref.prehash(hello), hello)); EXPECT_EQ(hello, *ref.find(ref.prehash(hello), hello));
// contains
EXPECT_FALSE(ref.contains(buddy));
EXPECT_TRUE(ref.contains(hello));
// equal_range // equal_range
EXPECT_TRUE(std::make_pair(ref.end(), ref.end()) == ref.equal_range(buddy)); EXPECT_TRUE(std::make_pair(ref.end(), ref.end()) == ref.equal_range(buddy));
EXPECT_TRUE( EXPECT_TRUE(
...@@ -1073,6 +1088,7 @@ void runHeterogeneousInsertTest() { ...@@ -1073,6 +1088,7 @@ void runHeterogeneousInsertTest() {
resetTracking(); resetTracking();
EXPECT_EQ(set.count(10), 0); EXPECT_EQ(set.count(10), 0);
EXPECT_FALSE(set.contains(10));
EXPECT_EQ(Tracked<1>::counts.dist(Counts{0, 0, 0, 0}), 0) EXPECT_EQ(Tracked<1>::counts.dist(Counts{0, 0, 0, 0}), 0)
<< Tracked<1>::counts; << Tracked<1>::counts;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment