Commit cad715db by Abseil Team Committed by Andy Getz

Export of internal Abseil changes

--
e2a571b818faaec4185426a8cf71fd2970674423 by Matt Kulukundis <kfm@google.com>:

Fix missed use of old RTTI macro

PiperOrigin-RevId: 413239579

--
e3c15a3fe0a4e44d6e08d69ad912b2245a403bd6 by Derek Mauro <dmauro@google.com>:

Makes erase_if return the number of erased elements for compatibility
with C++20

https://en.cppreference.com/w/cpp/container/unordered_map/erase_if

This may technically be an API break, but no actual breaks were found
in Google code. Fixes to open source code should be trivial.

Closes #1065

PiperOrigin-RevId: 413204392

--
c1fb1ddbc2def3f3d177e5b80b9934bdbb7b16fc by Matt Kulukundis <kfm@google.com>:

Consolidate to a single HAS_RTTI macro

PiperOrigin-RevId: 413169336
GitOrigin-RevId: e2a571b818faaec4185426a8cf71fd2970674423
Change-Id: I74b78ebd5fc172e3f5fcbd13a58cf53f7b250ae9
parent 3e1983c5
...@@ -788,4 +788,12 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' || ...@@ -788,4 +788,12 @@ static_assert(ABSL_INTERNAL_INLINE_NAMESPACE_STR[0] != 'h' ||
#define ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION 1 #define ABSL_HAVE_CLASS_TEMPLATE_ARGUMENT_DEDUCTION 1
#endif #endif
// `ABSL_INTERNAL_HAS_RTTI` determines whether abseil is being compiled with
// RTTI support.
#ifdef ABSL_INTERNAL_HAS_RTTI
#error ABSL_INTERNAL_HAS_RTTI cannot be directly set
#elif !defined(__GNUC__) || defined(__GXX_RTTI)
#define ABSL_INTERNAL_HAS_RTTI 1
#endif // !defined(__GNUC__) || defined(__GXX_RTTI)
#endif // ABSL_BASE_CONFIG_H_ #endif // ABSL_BASE_CONFIG_H_
...@@ -478,8 +478,11 @@ void swap(btree_map<K, V, C, A> &x, btree_map<K, V, C, A> &y) { ...@@ -478,8 +478,11 @@ void swap(btree_map<K, V, C, A> &x, btree_map<K, V, C, A> &y) {
// absl::erase_if(absl::btree_map<>, Pred) // absl::erase_if(absl::btree_map<>, Pred)
// //
// Erases all elements that satisfy the predicate pred from the container. // Erases all elements that satisfy the predicate pred from the container.
// Returns the number of erased elements.
template <typename K, typename V, typename C, typename A, typename Pred> template <typename K, typename V, typename C, typename A, typename Pred>
void erase_if(btree_map<K, V, C, A> &map, Pred pred) { typename btree_map<K, V, C, A>::size_type erase_if(
btree_map<K, V, C, A> &map, Pred pred) {
const auto initial_size = map.size();
for (auto it = map.begin(); it != map.end();) { for (auto it = map.begin(); it != map.end();) {
if (pred(*it)) { if (pred(*it)) {
it = map.erase(it); it = map.erase(it);
...@@ -487,6 +490,7 @@ void erase_if(btree_map<K, V, C, A> &map, Pred pred) { ...@@ -487,6 +490,7 @@ void erase_if(btree_map<K, V, C, A> &map, Pred pred) {
++it; ++it;
} }
} }
return initial_size - map.size();
} }
// absl::btree_multimap // absl::btree_multimap
...@@ -809,8 +813,11 @@ void swap(btree_multimap<K, V, C, A> &x, btree_multimap<K, V, C, A> &y) { ...@@ -809,8 +813,11 @@ void swap(btree_multimap<K, V, C, A> &x, btree_multimap<K, V, C, A> &y) {
// absl::erase_if(absl::btree_multimap<>, Pred) // absl::erase_if(absl::btree_multimap<>, Pred)
// //
// Erases all elements that satisfy the predicate pred from the container. // Erases all elements that satisfy the predicate pred from the container.
// Returns the number of erased elements.
template <typename K, typename V, typename C, typename A, typename Pred> template <typename K, typename V, typename C, typename A, typename Pred>
void erase_if(btree_multimap<K, V, C, A> &map, Pred pred) { typename btree_multimap<K, V, C, A>::size_type erase_if(
btree_multimap<K, V, C, A> &map, Pred pred) {
const auto initial_size = map.size();
for (auto it = map.begin(); it != map.end();) { for (auto it = map.begin(); it != map.end();) {
if (pred(*it)) { if (pred(*it)) {
it = map.erase(it); it = map.erase(it);
...@@ -818,6 +825,7 @@ void erase_if(btree_multimap<K, V, C, A> &map, Pred pred) { ...@@ -818,6 +825,7 @@ void erase_if(btree_multimap<K, V, C, A> &map, Pred pred) {
++it; ++it;
} }
} }
return initial_size - map.size();
} }
namespace container_internal { namespace container_internal {
......
...@@ -398,8 +398,11 @@ void swap(btree_set<K, C, A> &x, btree_set<K, C, A> &y) { ...@@ -398,8 +398,11 @@ void swap(btree_set<K, C, A> &x, btree_set<K, C, A> &y) {
// absl::erase_if(absl::btree_set<>, Pred) // absl::erase_if(absl::btree_set<>, Pred)
// //
// Erases all elements that satisfy the predicate pred from the container. // Erases all elements that satisfy the predicate pred from the container.
// Returns the number of erased elements.
template <typename K, typename C, typename A, typename Pred> template <typename K, typename C, typename A, typename Pred>
void erase_if(btree_set<K, C, A> &set, Pred pred) { typename btree_set<K, C, A>::size_type erase_if(btree_set<K, C, A> &set,
Pred pred) {
const auto initial_size = set.size();
for (auto it = set.begin(); it != set.end();) { for (auto it = set.begin(); it != set.end();) {
if (pred(*it)) { if (pred(*it)) {
it = set.erase(it); it = set.erase(it);
...@@ -407,6 +410,7 @@ void erase_if(btree_set<K, C, A> &set, Pred pred) { ...@@ -407,6 +410,7 @@ void erase_if(btree_set<K, C, A> &set, Pred pred) {
++it; ++it;
} }
} }
return initial_size - set.size();
} }
// absl::btree_multiset<> // absl::btree_multiset<>
...@@ -724,8 +728,11 @@ void swap(btree_multiset<K, C, A> &x, btree_multiset<K, C, A> &y) { ...@@ -724,8 +728,11 @@ void swap(btree_multiset<K, C, A> &x, btree_multiset<K, C, A> &y) {
// absl::erase_if(absl::btree_multiset<>, Pred) // absl::erase_if(absl::btree_multiset<>, Pred)
// //
// Erases all elements that satisfy the predicate pred from the container. // Erases all elements that satisfy the predicate pred from the container.
// Returns the number of erased elements.
template <typename K, typename C, typename A, typename Pred> template <typename K, typename C, typename A, typename Pred>
void erase_if(btree_multiset<K, C, A> &set, Pred pred) { typename btree_multiset<K, C, A>::size_type erase_if(
btree_multiset<K, C, A> & set, Pred pred) {
const auto initial_size = set.size();
for (auto it = set.begin(); it != set.end();) { for (auto it = set.begin(); it != set.end();) {
if (pred(*it)) { if (pred(*it)) {
it = set.erase(it); it = set.erase(it);
...@@ -733,6 +740,7 @@ void erase_if(btree_multiset<K, C, A> &set, Pred pred) { ...@@ -733,6 +740,7 @@ void erase_if(btree_multiset<K, C, A> &set, Pred pred) {
++it; ++it;
} }
} }
return initial_size - set.size();
} }
namespace container_internal { namespace container_internal {
......
...@@ -2452,23 +2452,28 @@ TEST(Btree, EraseIf) { ...@@ -2452,23 +2452,28 @@ TEST(Btree, EraseIf) {
// Test that erase_if works with all the container types and supports lambdas. // Test that erase_if works with all the container types and supports lambdas.
{ {
absl::btree_set<int> s = {1, 3, 5, 6, 100}; absl::btree_set<int> s = {1, 3, 5, 6, 100};
erase_if(s, [](int k) { return k > 3; }); EXPECT_EQ(erase_if(s, [](int k) { return k > 3; }), 3);
EXPECT_THAT(s, ElementsAre(1, 3)); EXPECT_THAT(s, ElementsAre(1, 3));
} }
{ {
absl::btree_multiset<int> s = {1, 3, 3, 5, 6, 6, 100}; absl::btree_multiset<int> s = {1, 3, 3, 5, 6, 6, 100};
erase_if(s, [](int k) { return k <= 3; }); EXPECT_EQ(erase_if(s, [](int k) { return k <= 3; }), 3);
EXPECT_THAT(s, ElementsAre(5, 6, 6, 100)); EXPECT_THAT(s, ElementsAre(5, 6, 6, 100));
} }
{ {
absl::btree_map<int, int> m = {{1, 1}, {3, 3}, {6, 6}, {100, 100}}; absl::btree_map<int, int> m = {{1, 1}, {3, 3}, {6, 6}, {100, 100}};
erase_if(m, [](std::pair<const int, int> kv) { return kv.first > 3; }); EXPECT_EQ(
erase_if(m, [](std::pair<const int, int> kv) { return kv.first > 3; }),
2);
EXPECT_THAT(m, ElementsAre(Pair(1, 1), Pair(3, 3))); EXPECT_THAT(m, ElementsAre(Pair(1, 1), Pair(3, 3)));
} }
{ {
absl::btree_multimap<int, int> m = {{1, 1}, {3, 3}, {3, 6}, absl::btree_multimap<int, int> m = {{1, 1}, {3, 3}, {3, 6},
{6, 6}, {6, 7}, {100, 6}}; {6, 6}, {6, 7}, {100, 6}};
erase_if(m, [](std::pair<const int, int> kv) { return kv.second == 6; }); EXPECT_EQ(
erase_if(m,
[](std::pair<const int, int> kv) { return kv.second == 6; }),
3);
EXPECT_THAT(m, ElementsAre(Pair(1, 1), Pair(3, 3), Pair(6, 7))); EXPECT_THAT(m, ElementsAre(Pair(1, 1), Pair(3, 3), Pair(6, 7)));
} }
// Test that erasing all elements from a large set works and test support for // Test that erasing all elements from a large set works and test support for
...@@ -2476,13 +2481,13 @@ TEST(Btree, EraseIf) { ...@@ -2476,13 +2481,13 @@ TEST(Btree, EraseIf) {
{ {
absl::btree_set<int> s; absl::btree_set<int> s;
for (int i = 0; i < 1000; ++i) s.insert(2 * i); for (int i = 0; i < 1000; ++i) s.insert(2 * i);
erase_if(s, IsEven); EXPECT_EQ(erase_if(s, IsEven), 1000);
EXPECT_THAT(s, IsEmpty()); EXPECT_THAT(s, IsEmpty());
} }
// Test that erase_if supports other format of function pointers. // Test that erase_if supports other format of function pointers.
{ {
absl::btree_set<int> s = {1, 3, 5, 6, 100}; absl::btree_set<int> s = {1, 3, 5, 6, 100};
erase_if(s, &IsEven); EXPECT_EQ(erase_if(s, &IsEven), 2);
EXPECT_THAT(s, ElementsAre(1, 3, 5)); EXPECT_THAT(s, ElementsAre(1, 3, 5));
} }
} }
......
...@@ -541,10 +541,12 @@ class flat_hash_map : public absl::container_internal::raw_hash_map< ...@@ -541,10 +541,12 @@ class flat_hash_map : public absl::container_internal::raw_hash_map<
// erase_if(flat_hash_map<>, Pred) // erase_if(flat_hash_map<>, Pred)
// //
// Erases all elements that satisfy the predicate `pred` from the container `c`. // Erases all elements that satisfy the predicate `pred` from the container `c`.
// Returns the number of erased elements.
template <typename K, typename V, typename H, typename E, typename A, template <typename K, typename V, typename H, typename E, typename A,
typename Predicate> typename Predicate>
void erase_if(flat_hash_map<K, V, H, E, A>& c, Predicate pred) { typename flat_hash_map<K, V, H, E, A>::size_type erase_if(
container_internal::EraseIf(pred, &c); flat_hash_map<K, V, H, E, A>& c, Predicate pred) {
return container_internal::EraseIf(pred, &c);
} }
namespace container_internal { namespace container_internal {
......
...@@ -236,33 +236,36 @@ TEST(FlatHashMap, EraseIf) { ...@@ -236,33 +236,36 @@ TEST(FlatHashMap, EraseIf) {
// Erase all elements. // Erase all elements.
{ {
flat_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}}; flat_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}};
erase_if(s, [](std::pair<const int, int>) { return true; }); EXPECT_EQ(erase_if(s, [](std::pair<const int, int>) { return true; }), 5);
EXPECT_THAT(s, IsEmpty()); EXPECT_THAT(s, IsEmpty());
} }
// Erase no elements. // Erase no elements.
{ {
flat_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}}; flat_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}};
erase_if(s, [](std::pair<const int, int>) { return false; }); EXPECT_EQ(erase_if(s, [](std::pair<const int, int>) { return false; }), 0);
EXPECT_THAT(s, UnorderedElementsAre(Pair(1, 1), Pair(2, 2), Pair(3, 3), EXPECT_THAT(s, UnorderedElementsAre(Pair(1, 1), Pair(2, 2), Pair(3, 3),
Pair(4, 4), Pair(5, 5))); Pair(4, 4), Pair(5, 5)));
} }
// Erase specific elements. // Erase specific elements.
{ {
flat_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}}; flat_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}};
erase_if(s, EXPECT_EQ(erase_if(s,
[](std::pair<const int, int> kvp) { return kvp.first % 2 == 1; }); [](std::pair<const int, int> kvp) {
return kvp.first % 2 == 1;
}),
3);
EXPECT_THAT(s, UnorderedElementsAre(Pair(2, 2), Pair(4, 4))); EXPECT_THAT(s, UnorderedElementsAre(Pair(2, 2), Pair(4, 4)));
} }
// Predicate is function reference. // Predicate is function reference.
{ {
flat_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}}; flat_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}};
erase_if(s, FirstIsEven); EXPECT_EQ(erase_if(s, FirstIsEven), 2);
EXPECT_THAT(s, UnorderedElementsAre(Pair(1, 1), Pair(3, 3), Pair(5, 5))); EXPECT_THAT(s, UnorderedElementsAre(Pair(1, 1), Pair(3, 3), Pair(5, 5)));
} }
// Predicate is function pointer. // Predicate is function pointer.
{ {
flat_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}}; flat_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}};
erase_if(s, &FirstIsEven); EXPECT_EQ(erase_if(s, &FirstIsEven), 2);
EXPECT_THAT(s, UnorderedElementsAre(Pair(1, 1), Pair(3, 3), Pair(5, 5))); EXPECT_THAT(s, UnorderedElementsAre(Pair(1, 1), Pair(3, 3), Pair(5, 5)));
} }
} }
......
...@@ -443,9 +443,11 @@ class flat_hash_set ...@@ -443,9 +443,11 @@ class flat_hash_set
// erase_if(flat_hash_set<>, Pred) // erase_if(flat_hash_set<>, Pred)
// //
// Erases all elements that satisfy the predicate `pred` from the container `c`. // Erases all elements that satisfy the predicate `pred` from the container `c`.
// Returns the number of erased elements.
template <typename T, typename H, typename E, typename A, typename Predicate> template <typename T, typename H, typename E, typename A, typename Predicate>
void erase_if(flat_hash_set<T, H, E, A>& c, Predicate pred) { typename flat_hash_set<T, H, E, A>::size_type erase_if(
container_internal::EraseIf(pred, &c); flat_hash_set<T, H, E, A>& c, Predicate pred) {
return container_internal::EraseIf(pred, &c);
} }
namespace container_internal { namespace container_internal {
......
...@@ -143,31 +143,31 @@ TEST(FlatHashSet, EraseIf) { ...@@ -143,31 +143,31 @@ TEST(FlatHashSet, EraseIf) {
// Erase all elements. // Erase all elements.
{ {
flat_hash_set<int> s = {1, 2, 3, 4, 5}; flat_hash_set<int> s = {1, 2, 3, 4, 5};
erase_if(s, [](int) { return true; }); EXPECT_EQ(erase_if(s, [](int) { return true; }), 5);
EXPECT_THAT(s, IsEmpty()); EXPECT_THAT(s, IsEmpty());
} }
// Erase no elements. // Erase no elements.
{ {
flat_hash_set<int> s = {1, 2, 3, 4, 5}; flat_hash_set<int> s = {1, 2, 3, 4, 5};
erase_if(s, [](int) { return false; }); EXPECT_EQ(erase_if(s, [](int) { return false; }), 0);
EXPECT_THAT(s, UnorderedElementsAre(1, 2, 3, 4, 5)); EXPECT_THAT(s, UnorderedElementsAre(1, 2, 3, 4, 5));
} }
// Erase specific elements. // Erase specific elements.
{ {
flat_hash_set<int> s = {1, 2, 3, 4, 5}; flat_hash_set<int> s = {1, 2, 3, 4, 5};
erase_if(s, [](int k) { return k % 2 == 1; }); EXPECT_EQ(erase_if(s, [](int k) { return k % 2 == 1; }), 3);
EXPECT_THAT(s, UnorderedElementsAre(2, 4)); EXPECT_THAT(s, UnorderedElementsAre(2, 4));
} }
// Predicate is function reference. // Predicate is function reference.
{ {
flat_hash_set<int> s = {1, 2, 3, 4, 5}; flat_hash_set<int> s = {1, 2, 3, 4, 5};
erase_if(s, IsEven); EXPECT_EQ(erase_if(s, IsEven), 2);
EXPECT_THAT(s, UnorderedElementsAre(1, 3, 5)); EXPECT_THAT(s, UnorderedElementsAre(1, 3, 5));
} }
// Predicate is function pointer. // Predicate is function pointer.
{ {
flat_hash_set<int> s = {1, 2, 3, 4, 5}; flat_hash_set<int> s = {1, 2, 3, 4, 5};
erase_if(s, &IsEven); EXPECT_EQ(erase_if(s, &IsEven), 2);
EXPECT_THAT(s, UnorderedElementsAre(1, 3, 5)); EXPECT_THAT(s, UnorderedElementsAre(1, 3, 5));
} }
} }
......
...@@ -1958,7 +1958,9 @@ class raw_hash_set { ...@@ -1958,7 +1958,9 @@ class raw_hash_set {
// Erases all elements that satisfy the predicate `pred` from the container `c`. // Erases all elements that satisfy the predicate `pred` from the container `c`.
template <typename P, typename H, typename E, typename A, typename Predicate> template <typename P, typename H, typename E, typename A, typename Predicate>
void EraseIf(Predicate& pred, raw_hash_set<P, H, E, A>* c) { typename raw_hash_set<P, H, E, A>::size_type EraseIf(
Predicate& pred, raw_hash_set<P, H, E, A>* c) {
const auto initial_size = c->size();
for (auto it = c->begin(), last = c->end(); it != last;) { for (auto it = c->begin(), last = c->end(); it != last;) {
if (pred(*it)) { if (pred(*it)) {
c->erase(it++); c->erase(it++);
...@@ -1966,6 +1968,7 @@ void EraseIf(Predicate& pred, raw_hash_set<P, H, E, A>* c) { ...@@ -1966,6 +1968,7 @@ void EraseIf(Predicate& pred, raw_hash_set<P, H, E, A>* c) {
++it; ++it;
} }
} }
return initial_size - c->size();
} }
namespace hashtable_debug_internal { namespace hashtable_debug_internal {
......
...@@ -525,10 +525,12 @@ class node_hash_map ...@@ -525,10 +525,12 @@ class node_hash_map
// erase_if(node_hash_map<>, Pred) // erase_if(node_hash_map<>, Pred)
// //
// Erases all elements that satisfy the predicate `pred` from the container `c`. // Erases all elements that satisfy the predicate `pred` from the container `c`.
// Returns the number of erased elements.
template <typename K, typename V, typename H, typename E, typename A, template <typename K, typename V, typename H, typename E, typename A,
typename Predicate> typename Predicate>
void erase_if(node_hash_map<K, V, H, E, A>& c, Predicate pred) { typename node_hash_map<K, V, H, E, A>::size_type erase_if(
container_internal::EraseIf(pred, &c); node_hash_map<K, V, H, E, A>& c, Predicate pred) {
return container_internal::EraseIf(pred, &c);
} }
namespace container_internal { namespace container_internal {
......
...@@ -223,33 +223,36 @@ TEST(NodeHashMap, EraseIf) { ...@@ -223,33 +223,36 @@ TEST(NodeHashMap, EraseIf) {
// Erase all elements. // Erase all elements.
{ {
node_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}}; node_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}};
erase_if(s, [](std::pair<const int, int>) { return true; }); EXPECT_EQ(erase_if(s, [](std::pair<const int, int>) { return true; }), 5);
EXPECT_THAT(s, IsEmpty()); EXPECT_THAT(s, IsEmpty());
} }
// Erase no elements. // Erase no elements.
{ {
node_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}}; node_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}};
erase_if(s, [](std::pair<const int, int>) { return false; }); EXPECT_EQ(erase_if(s, [](std::pair<const int, int>) { return false; }), 0);
EXPECT_THAT(s, UnorderedElementsAre(Pair(1, 1), Pair(2, 2), Pair(3, 3), EXPECT_THAT(s, UnorderedElementsAre(Pair(1, 1), Pair(2, 2), Pair(3, 3),
Pair(4, 4), Pair(5, 5))); Pair(4, 4), Pair(5, 5)));
} }
// Erase specific elements. // Erase specific elements.
{ {
node_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}}; node_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}};
erase_if(s, EXPECT_EQ(erase_if(s,
[](std::pair<const int, int> kvp) { return kvp.first % 2 == 1; }); [](std::pair<const int, int> kvp) {
return kvp.first % 2 == 1;
}),
3);
EXPECT_THAT(s, UnorderedElementsAre(Pair(2, 2), Pair(4, 4))); EXPECT_THAT(s, UnorderedElementsAre(Pair(2, 2), Pair(4, 4)));
} }
// Predicate is function reference. // Predicate is function reference.
{ {
node_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}}; node_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}};
erase_if(s, FirstIsEven); EXPECT_EQ(erase_if(s, FirstIsEven), 2);
EXPECT_THAT(s, UnorderedElementsAre(Pair(1, 1), Pair(3, 3), Pair(5, 5))); EXPECT_THAT(s, UnorderedElementsAre(Pair(1, 1), Pair(3, 3), Pair(5, 5)));
} }
// Predicate is function pointer. // Predicate is function pointer.
{ {
node_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}}; node_hash_map<int, int> s = {{1, 1}, {2, 2}, {3, 3}, {4, 4}, {5, 5}};
erase_if(s, &FirstIsEven); EXPECT_EQ(erase_if(s, &FirstIsEven), 2);
EXPECT_THAT(s, UnorderedElementsAre(Pair(1, 1), Pair(3, 3), Pair(5, 5))); EXPECT_THAT(s, UnorderedElementsAre(Pair(1, 1), Pair(3, 3), Pair(5, 5)));
} }
} }
......
...@@ -433,9 +433,11 @@ class node_hash_set ...@@ -433,9 +433,11 @@ class node_hash_set
// erase_if(node_hash_set<>, Pred) // erase_if(node_hash_set<>, Pred)
// //
// Erases all elements that satisfy the predicate `pred` from the container `c`. // Erases all elements that satisfy the predicate `pred` from the container `c`.
// Returns the number of erased elements.
template <typename T, typename H, typename E, typename A, typename Predicate> template <typename T, typename H, typename E, typename A, typename Predicate>
void erase_if(node_hash_set<T, H, E, A>& c, Predicate pred) { typename node_hash_set<T, H, E, A>::size_type erase_if(
container_internal::EraseIf(pred, &c); node_hash_set<T, H, E, A>& c, Predicate pred) {
return container_internal::EraseIf(pred, &c);
} }
namespace container_internal { namespace container_internal {
......
...@@ -108,31 +108,31 @@ TEST(NodeHashSet, EraseIf) { ...@@ -108,31 +108,31 @@ TEST(NodeHashSet, EraseIf) {
// Erase all elements. // Erase all elements.
{ {
node_hash_set<int> s = {1, 2, 3, 4, 5}; node_hash_set<int> s = {1, 2, 3, 4, 5};
erase_if(s, [](int) { return true; }); EXPECT_EQ(erase_if(s, [](int) { return true; }), 5);
EXPECT_THAT(s, IsEmpty()); EXPECT_THAT(s, IsEmpty());
} }
// Erase no elements. // Erase no elements.
{ {
node_hash_set<int> s = {1, 2, 3, 4, 5}; node_hash_set<int> s = {1, 2, 3, 4, 5};
erase_if(s, [](int) { return false; }); EXPECT_EQ(erase_if(s, [](int) { return false; }), 0);
EXPECT_THAT(s, UnorderedElementsAre(1, 2, 3, 4, 5)); EXPECT_THAT(s, UnorderedElementsAre(1, 2, 3, 4, 5));
} }
// Erase specific elements. // Erase specific elements.
{ {
node_hash_set<int> s = {1, 2, 3, 4, 5}; node_hash_set<int> s = {1, 2, 3, 4, 5};
erase_if(s, [](int k) { return k % 2 == 1; }); EXPECT_EQ(erase_if(s, [](int k) { return k % 2 == 1; }), 3);
EXPECT_THAT(s, UnorderedElementsAre(2, 4)); EXPECT_THAT(s, UnorderedElementsAre(2, 4));
} }
// Predicate is function reference. // Predicate is function reference.
{ {
node_hash_set<int> s = {1, 2, 3, 4, 5}; node_hash_set<int> s = {1, 2, 3, 4, 5};
erase_if(s, IsEven); EXPECT_EQ(erase_if(s, IsEven), 2);
EXPECT_THAT(s, UnorderedElementsAre(1, 3, 5)); EXPECT_THAT(s, UnorderedElementsAre(1, 3, 5));
} }
// Predicate is function pointer. // Predicate is function pointer.
{ {
node_hash_set<int> s = {1, 2, 3, 4, 5}; node_hash_set<int> s = {1, 2, 3, 4, 5};
erase_if(s, &IsEven); EXPECT_EQ(erase_if(s, &IsEven), 2);
EXPECT_THAT(s, UnorderedElementsAre(1, 3, 5)); EXPECT_THAT(s, UnorderedElementsAre(1, 3, 5));
} }
} }
......
...@@ -45,14 +45,6 @@ ...@@ -45,14 +45,6 @@
#define ABSL_FLAGS_STRIP_HELP ABSL_FLAGS_STRIP_NAMES #define ABSL_FLAGS_STRIP_HELP ABSL_FLAGS_STRIP_NAMES
#endif #endif
// ABSL_FLAGS_INTERNAL_HAS_RTTI macro is used for selecting if we can use RTTI
// for flag type identification.
#ifdef ABSL_FLAGS_INTERNAL_HAS_RTTI
#error ABSL_FLAGS_INTERNAL_HAS_RTTI cannot be directly set
#elif !defined(__GNUC__) || defined(__GXX_RTTI)
#define ABSL_FLAGS_INTERNAL_HAS_RTTI 1
#endif // !defined(__GNUC__) || defined(__GXX_RTTI)
// These macros represent the "source of truth" for the list of supported // These macros represent the "source of truth" for the list of supported
// built-in types. // built-in types.
#define ABSL_FLAGS_INTERNAL_BUILTIN_TYPES(A) \ #define ABSL_FLAGS_INTERNAL_BUILTIN_TYPES(A) \
......
...@@ -205,7 +205,7 @@ void FlagImpl::AssertValidType(FlagFastTypeId rhs_type_id, ...@@ -205,7 +205,7 @@ void FlagImpl::AssertValidType(FlagFastTypeId rhs_type_id,
if (lhs_runtime_type_id == rhs_runtime_type_id) return; if (lhs_runtime_type_id == rhs_runtime_type_id) return;
#if defined(ABSL_FLAGS_INTERNAL_HAS_RTTI) #ifdef ABSL_INTERNAL_HAS_RTTI
if (*lhs_runtime_type_id == *rhs_runtime_type_id) return; if (*lhs_runtime_type_id == *rhs_runtime_type_id) return;
#endif #endif
......
...@@ -163,7 +163,7 @@ inline ptrdiff_t ValueOffset(FlagOpFn op) { ...@@ -163,7 +163,7 @@ inline ptrdiff_t ValueOffset(FlagOpFn op) {
// Returns an address of RTTI's typeid(T). // Returns an address of RTTI's typeid(T).
template <typename T> template <typename T>
inline const std::type_info* GenRuntimeTypeId() { inline const std::type_info* GenRuntimeTypeId() {
#if defined(ABSL_FLAGS_INTERNAL_HAS_RTTI) #ifdef ABSL_INTERNAL_HAS_RTTI
return &typeid(T); return &typeid(T);
#else #else
return nullptr; return nullptr;
......
...@@ -81,18 +81,9 @@ ABSL_NAMESPACE_END ...@@ -81,18 +81,9 @@ ABSL_NAMESPACE_END
#include <utility> #include <utility>
#include "absl/base/internal/fast_type_id.h" #include "absl/base/internal/fast_type_id.h"
#include "absl/base/macros.h"
#include "absl/meta/type_traits.h" #include "absl/meta/type_traits.h"
#include "absl/types/bad_any_cast.h" #include "absl/types/bad_any_cast.h"
// NOTE: This macro is an implementation detail that is undefined at the bottom
// of the file. It is not intended for expansion directly from user code.
#ifdef ABSL_ANY_DETAIL_HAS_RTTI
#error ABSL_ANY_DETAIL_HAS_RTTI cannot be directly set
#elif !defined(__GNUC__) || defined(__GXX_RTTI)
#define ABSL_ANY_DETAIL_HAS_RTTI 1
#endif // !defined(__GNUC__) || defined(__GXX_RTTI)
namespace absl { namespace absl {
ABSL_NAMESPACE_BEGIN ABSL_NAMESPACE_BEGIN
...@@ -348,7 +339,7 @@ class any { ...@@ -348,7 +339,7 @@ class any {
// returns `false`. // returns `false`.
bool has_value() const noexcept { return obj_ != nullptr; } bool has_value() const noexcept { return obj_ != nullptr; }
#if ABSL_ANY_DETAIL_HAS_RTTI #ifdef ABSL_INTERNAL_HAS_RTTI
// Returns: typeid(T) if *this has a contained object of type T, otherwise // Returns: typeid(T) if *this has a contained object of type T, otherwise
// typeid(void). // typeid(void).
const std::type_info& type() const noexcept { const std::type_info& type() const noexcept {
...@@ -358,7 +349,7 @@ class any { ...@@ -358,7 +349,7 @@ class any {
return typeid(void); return typeid(void);
} }
#endif // ABSL_ANY_DETAIL_HAS_RTTI #endif // ABSL_INTERNAL_HAS_RTTI
private: private:
// Tagged type-erased abstraction for holding a cloneable object. // Tagged type-erased abstraction for holding a cloneable object.
...@@ -367,9 +358,9 @@ class any { ...@@ -367,9 +358,9 @@ class any {
virtual ~ObjInterface() = default; virtual ~ObjInterface() = default;
virtual std::unique_ptr<ObjInterface> Clone() const = 0; virtual std::unique_ptr<ObjInterface> Clone() const = 0;
virtual const void* ObjTypeId() const noexcept = 0; virtual const void* ObjTypeId() const noexcept = 0;
#if ABSL_ANY_DETAIL_HAS_RTTI #ifdef ABSL_INTERNAL_HAS_RTTI
virtual const std::type_info& Type() const noexcept = 0; virtual const std::type_info& Type() const noexcept = 0;
#endif // ABSL_ANY_DETAIL_HAS_RTTI #endif // ABSL_INTERNAL_HAS_RTTI
}; };
// Hold a value of some queryable type, with an ability to Clone it. // Hold a value of some queryable type, with an ability to Clone it.
...@@ -386,9 +377,9 @@ class any { ...@@ -386,9 +377,9 @@ class any {
const void* ObjTypeId() const noexcept final { return IdForType<T>(); } const void* ObjTypeId() const noexcept final { return IdForType<T>(); }
#if ABSL_ANY_DETAIL_HAS_RTTI #ifdef ABSL_INTERNAL_HAS_RTTI
const std::type_info& Type() const noexcept final { return typeid(T); } const std::type_info& Type() const noexcept final { return typeid(T); }
#endif // ABSL_ANY_DETAIL_HAS_RTTI #endif // ABSL_INTERNAL_HAS_RTTI
T value; T value;
}; };
...@@ -521,8 +512,6 @@ T* any_cast(any* operand) noexcept { ...@@ -521,8 +512,6 @@ T* any_cast(any* operand) noexcept {
ABSL_NAMESPACE_END ABSL_NAMESPACE_END
} // namespace absl } // namespace absl
#undef ABSL_ANY_DETAIL_HAS_RTTI
#endif // ABSL_USES_STD_ANY #endif // ABSL_USES_STD_ANY
#endif // ABSL_TYPES_ANY_H_ #endif // ABSL_TYPES_ANY_H_
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