diff options
-rw-r--r-- | absl/container/BUILD.bazel | 12 | ||||
-rw-r--r-- | absl/container/CMakeLists.txt | 11 | ||||
-rw-r--r-- | absl/container/flat_hash_map.h | 33 | ||||
-rw-r--r-- | absl/container/flat_hash_map_test.cc | 53 | ||||
-rw-r--r-- | absl/container/flat_hash_set.h | 28 | ||||
-rw-r--r-- | absl/container/flat_hash_set_test.cc | 33 | ||||
-rw-r--r-- | absl/container/internal/raw_hash_set.h | 27 | ||||
-rw-r--r-- | absl/container/internal/raw_hash_set_test.cc | 52 | ||||
-rw-r--r-- | absl/container/node_hash_map.h | 33 | ||||
-rw-r--r-- | absl/container/node_hash_map_test.cc | 65 | ||||
-rw-r--r-- | absl/container/node_hash_set.h | 28 | ||||
-rw-r--r-- | absl/container/node_hash_set_test.cc | 46 |
12 files changed, 417 insertions, 4 deletions
diff --git a/absl/container/BUILD.bazel b/absl/container/BUILD.bazel index 38fec260..b00c30fd 100644 --- a/absl/container/BUILD.bazel +++ b/absl/container/BUILD.bazel @@ -252,7 +252,7 @@ cc_library( ":raw_hash_map", "//absl/algorithm:container", "//absl/base:core_headers", - "//absl/memory", + "//absl/meta:type_traits", ], ) @@ -292,6 +292,7 @@ cc_library( "//absl/algorithm:container", "//absl/base:core_headers", "//absl/memory", + "//absl/meta:type_traits", ], ) @@ -332,6 +333,7 @@ cc_library( "//absl/algorithm:container", "//absl/base:core_headers", "//absl/memory", + "//absl/meta:type_traits", ], ) @@ -342,13 +344,14 @@ cc_test( linkopts = ABSL_DEFAULT_LINKOPTS, tags = ["no_test_loonix"], deps = [ - ":hash_generator_testing", + ":hash_policy_testing", ":node_hash_map", ":tracked", ":unordered_map_constructor_test", ":unordered_map_lookup_test", ":unordered_map_members_test", ":unordered_map_modifiers_test", + "//absl/base:config", "@com_google_googletest//:gtest", "@com_google_googletest//:gtest_main", ], @@ -367,6 +370,7 @@ cc_library( "//absl/algorithm:container", "//absl/base:core_headers", "//absl/memory", + "//absl/meta:type_traits", ], ) @@ -377,11 +381,15 @@ cc_test( linkopts = ABSL_DEFAULT_LINKOPTS, tags = ["no_test_loonix"], deps = [ + ":hash_generator_testing", + ":hash_policy_testing", ":node_hash_set", ":unordered_set_constructor_test", ":unordered_set_lookup_test", ":unordered_set_members_test", ":unordered_set_modifiers_test", + "//absl/base:config", + "//absl/memory", "@com_google_googletest//:gtest", "@com_google_googletest//:gtest_main", ], diff --git a/absl/container/CMakeLists.txt b/absl/container/CMakeLists.txt index dd994f0b..25831d5f 100644 --- a/absl/container/CMakeLists.txt +++ b/absl/container/CMakeLists.txt @@ -292,7 +292,7 @@ absl_cc_library( absl::hash_container_defaults absl::raw_hash_map absl::algorithm_container - absl::memory + absl::type_traits PUBLIC ) @@ -333,6 +333,7 @@ absl_cc_library( absl::algorithm_container absl::core_headers absl::memory + absl::type_traits PUBLIC ) @@ -375,6 +376,7 @@ absl_cc_library( absl::raw_hash_map absl::algorithm_container absl::memory + absl::type_traits PUBLIC ) @@ -386,7 +388,8 @@ absl_cc_test( COPTS ${ABSL_TEST_COPTS} DEPS - absl::hash_generator_testing + absl::config + absl::hash_policy_testing absl::node_hash_map absl::tracked absl::unordered_map_constructor_test @@ -411,6 +414,7 @@ absl_cc_library( absl::raw_hash_set absl::algorithm_container absl::memory + absl::type_traits PUBLIC ) @@ -424,7 +428,10 @@ absl_cc_test( "-DUNORDERED_SET_CXX17" DEPS absl::hash_generator_testing + absl::hash_policy_testing + absl::memory absl::node_hash_set + absl::type_traits absl::unordered_set_constructor_test absl::unordered_set_lookup_test absl::unordered_set_members_test diff --git a/absl/container/flat_hash_map.h b/absl/container/flat_hash_map.h index 3eae404f..ebd9ed67 100644 --- a/absl/container/flat_hash_map.h +++ b/absl/container/flat_hash_map.h @@ -43,6 +43,7 @@ #include "absl/container/hash_container_defaults.h" #include "absl/container/internal/container_memory.h" #include "absl/container/internal/raw_hash_map.h" // IWYU pragma: export +#include "absl/meta/type_traits.h" namespace absl { ABSL_NAMESPACE_BEGIN @@ -575,6 +576,38 @@ typename flat_hash_map<K, V, H, E, A>::size_type erase_if( namespace container_internal { +// c_for_each_fast(flat_hash_map<>, Function) +// +// Container-based version of the <algorithm> `std::for_each()` function to +// apply a function to a container's elements. +// There is no guarantees on the order of the function calls. +// Erasure and/or insertion of elements in the function is not allowed. +template <typename K, typename V, typename H, typename E, typename A, + typename Function> +decay_t<Function> c_for_each_fast(const flat_hash_map<K, V, H, E, A>& c, + Function&& f) { + container_internal::ForEach(f, &c); + return f; +} +template <typename K, typename V, typename H, typename E, typename A, + typename Function> +decay_t<Function> c_for_each_fast(flat_hash_map<K, V, H, E, A>& c, + Function&& f) { + container_internal::ForEach(f, &c); + return f; +} +template <typename K, typename V, typename H, typename E, typename A, + typename Function> +decay_t<Function> c_for_each_fast(flat_hash_map<K, V, H, E, A>&& c, + Function&& f) { + container_internal::ForEach(f, &c); + return f; +} + +} // namespace container_internal + +namespace container_internal { + template <class K, class V> struct FlatHashMapPolicy { using slot_policy = container_internal::map_slot_policy<K, V>; diff --git a/absl/container/flat_hash_map_test.cc b/absl/container/flat_hash_map_test.cc index eaa86925..08915e20 100644 --- a/absl/container/flat_hash_map_test.cc +++ b/absl/container/flat_hash_map_test.cc @@ -45,6 +45,7 @@ using ::testing::_; using ::testing::IsEmpty; using ::testing::Pair; using ::testing::UnorderedElementsAre; +using ::testing::UnorderedElementsAreArray; // Check that absl::flat_hash_map works in a global constructor. struct BeforeMain { @@ -307,6 +308,58 @@ TEST(FlatHashMap, EraseIf) { } } +TEST(FlatHashMap, CForEach) { + flat_hash_map<int, int> m; + std::vector<std::pair<int, int>> expected; + for (int i = 0; i < 100; ++i) { + { + SCOPED_TRACE("mutable object iteration"); + std::vector<std::pair<int, int>> v; + absl::container_internal::c_for_each_fast( + m, [&v](std::pair<const int, int>& p) { v.push_back(p); }); + EXPECT_THAT(v, UnorderedElementsAreArray(expected)); + } + { + SCOPED_TRACE("const object iteration"); + std::vector<std::pair<int, int>> v; + const flat_hash_map<int, int>& cm = m; + absl::container_internal::c_for_each_fast( + cm, [&v](const std::pair<const int, int>& p) { v.push_back(p); }); + EXPECT_THAT(v, UnorderedElementsAreArray(expected)); + } + { + SCOPED_TRACE("const object iteration"); + std::vector<std::pair<int, int>> v; + absl::container_internal::c_for_each_fast( + flat_hash_map<int, int>(m), + [&v](std::pair<const int, int>& p) { v.push_back(p); }); + EXPECT_THAT(v, UnorderedElementsAreArray(expected)); + } + m[i] = i; + expected.emplace_back(i, i); + } +} + +TEST(FlatHashMap, CForEachMutate) { + flat_hash_map<int, int> s; + std::vector<std::pair<int, int>> expected; + for (int i = 0; i < 100; ++i) { + std::vector<std::pair<int, int>> v; + absl::container_internal::c_for_each_fast( + s, [&v](std::pair<const int, int>& p) { + v.push_back(p); + p.second++; + }); + EXPECT_THAT(v, UnorderedElementsAreArray(expected)); + for (auto& p : expected) { + p.second++; + } + EXPECT_THAT(s, UnorderedElementsAreArray(expected)); + s[i] = i; + expected.emplace_back(i, i); + } +} + // This test requires std::launder for mutable key access in node handles. #if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606 TEST(FlatHashMap, NodeHandleMutableKeyAccess) { diff --git a/absl/container/flat_hash_set.h b/absl/container/flat_hash_set.h index e284a7df..a3e36e05 100644 --- a/absl/container/flat_hash_set.h +++ b/absl/container/flat_hash_set.h @@ -44,6 +44,7 @@ #include "absl/container/internal/container_memory.h" #include "absl/container/internal/raw_hash_set.h" // IWYU pragma: export #include "absl/memory/memory.h" +#include "absl/meta/type_traits.h" namespace absl { ABSL_NAMESPACE_BEGIN @@ -479,6 +480,33 @@ typename flat_hash_set<T, H, E, A>::size_type erase_if( namespace container_internal { +// c_for_each_fast(flat_hash_set<>, Function) +// +// Container-based version of the <algorithm> `std::for_each()` function to +// apply a function to a container's elements. +// There is no guarantees on the order of the function calls. +// Erasure and/or insertion of elements in the function is not allowed. +template <typename T, typename H, typename E, typename A, typename Function> +decay_t<Function> c_for_each_fast(const flat_hash_set<T, H, E, A>& c, + Function&& f) { + container_internal::ForEach(f, &c); + return f; +} +template <typename T, typename H, typename E, typename A, typename Function> +decay_t<Function> c_for_each_fast(flat_hash_set<T, H, E, A>& c, Function&& f) { + container_internal::ForEach(f, &c); + return f; +} +template <typename T, typename H, typename E, typename A, typename Function> +decay_t<Function> c_for_each_fast(flat_hash_set<T, H, E, A>&& c, Function&& f) { + container_internal::ForEach(f, &c); + return f; +} + +} // namespace container_internal + +namespace container_internal { + template <class T> struct FlatHashSetPolicy { using slot_type = T; diff --git a/absl/container/flat_hash_set_test.cc b/absl/container/flat_hash_set_test.cc index b425bc50..0dd43269 100644 --- a/absl/container/flat_hash_set_test.cc +++ b/absl/container/flat_hash_set_test.cc @@ -181,6 +181,39 @@ TEST(FlatHashSet, EraseIf) { } } +TEST(FlatHashSet, CForEach) { + using ValueType = std::pair<int, int>; + flat_hash_set<ValueType> s; + std::vector<ValueType> expected; + for (int i = 0; i < 100; ++i) { + { + SCOPED_TRACE("mutable object iteration"); + std::vector<ValueType> v; + absl::container_internal::c_for_each_fast( + s, [&v](const ValueType& p) { v.push_back(p); }); + ASSERT_THAT(v, UnorderedElementsAreArray(expected)); + } + { + SCOPED_TRACE("const object iteration"); + std::vector<ValueType> v; + const flat_hash_set<ValueType>& cs = s; + absl::container_internal::c_for_each_fast( + cs, [&v](const ValueType& p) { v.push_back(p); }); + ASSERT_THAT(v, UnorderedElementsAreArray(expected)); + } + { + SCOPED_TRACE("temporary object iteration"); + std::vector<ValueType> v; + absl::container_internal::c_for_each_fast( + flat_hash_set<ValueType>(s), + [&v](const ValueType& p) { v.push_back(p); }); + ASSERT_THAT(v, UnorderedElementsAreArray(expected)); + } + s.emplace(i, i); + expected.emplace_back(i, i); + } +} + class PoisonSoo { int64_t data_; diff --git a/absl/container/internal/raw_hash_set.h b/absl/container/internal/raw_hash_set.h index c63b60e3..a722f522 100644 --- a/absl/container/internal/raw_hash_set.h +++ b/absl/container/internal/raw_hash_set.h @@ -4075,6 +4075,23 @@ struct HashtableFreeFunctionsAccess { }); return num_deleted; } + + template <class Callback, typename Set> + static void ForEach(Callback& cb, Set* c) { + if (c->empty()) { + return; + } + if (c->is_soo()) { + cb(*c->soo_iterator()); + return; + } + using ElementTypeWithConstness = decltype(*c->begin()); + IterateOverFullSlots</*kAllowRemoveReentrance=*/false>( + c->common(), c->slot_array(), [&cb](const ctrl_t*, auto* slot) { + ElementTypeWithConstness& element = Set::PolicyTraits::element(slot); + cb(element); + }); + } }; // Erases all elements that satisfy the predicate `pred` from the container `c`. @@ -4084,6 +4101,16 @@ typename raw_hash_set<P, H, E, A>::size_type EraseIf( return HashtableFreeFunctionsAccess::EraseIf(pred, c); } +// Calls `cb` for all elements in the container `c`. +template <typename P, typename H, typename E, typename A, typename Callback> +void ForEach(Callback& cb, raw_hash_set<P, H, E, A>* c) { + return HashtableFreeFunctionsAccess::ForEach(cb, c); +} +template <typename P, typename H, typename E, typename A, typename Callback> +void ForEach(Callback& cb, const raw_hash_set<P, H, E, A>* c) { + return HashtableFreeFunctionsAccess::ForEach(cb, c); +} + namespace hashtable_debug_internal { template <typename Set> struct HashtableDebugAccess<Set, absl::void_t<typename Set::raw_hash_set>> { diff --git a/absl/container/internal/raw_hash_set_test.cc b/absl/container/internal/raw_hash_set_test.cc index 2a6ee656..673d78a6 100644 --- a/absl/container/internal/raw_hash_set_test.cc +++ b/absl/container/internal/raw_hash_set_test.cc @@ -3121,6 +3121,58 @@ TYPED_TEST(SooTest, EraseIfPartial) { } } +TYPED_TEST(SooTest, ForEach) { + TypeParam t; + std::vector<int64_t> expected; + for (int size = 0; size < 100; ++size) { + SCOPED_TRACE(size); + { + SCOPED_TRACE("mutable iteration"); + std::vector<int64_t> actual; + auto f = [&](auto& x) { actual.push_back(static_cast<int64_t>(x)); }; + absl::container_internal::ForEach(f, &t); + ASSERT_THAT(actual, testing::UnorderedElementsAreArray(expected)); + } + { + SCOPED_TRACE("const iteration"); + std::vector<int64_t> actual; + auto f = [&](auto& x) { + static_assert( + std::is_const<std::remove_reference_t<decltype(x)>>::value, + "no mutable values should be passed to const ForEach"); + actual.push_back(static_cast<int64_t>(x)); + }; + const auto& ct = t; + absl::container_internal::ForEach(f, &ct); + ASSERT_THAT(actual, testing::UnorderedElementsAreArray(expected)); + } + t.insert(size); + expected.push_back(size); + } +} + +TEST(Table, ForEachMutate) { + StringTable t; + using ValueType = StringTable::value_type; + std::vector<ValueType> expected; + for (int size = 0; size < 100; ++size) { + SCOPED_TRACE(size); + std::vector<ValueType> actual; + auto f = [&](ValueType& x) { + actual.push_back(x); + x.second += "a"; + }; + absl::container_internal::ForEach(f, &t); + ASSERT_THAT(actual, testing::UnorderedElementsAreArray(expected)); + for (ValueType& v : expected) { + v.second += "a"; + } + ASSERT_THAT(t, testing::UnorderedElementsAreArray(expected)); + t.emplace(std::to_string(size), std::to_string(size)); + expected.emplace_back(std::to_string(size), std::to_string(size)); + } +} + TEST(Table, EraseBeginEndResetsReservedGrowth) { bool frozen = false; BadHashFreezableIntTable t{FreezableAlloc<int64_t>(&frozen)}; diff --git a/absl/container/node_hash_map.h b/absl/container/node_hash_map.h index 7b74b4b3..5615e496 100644 --- a/absl/container/node_hash_map.h +++ b/absl/container/node_hash_map.h @@ -50,6 +50,7 @@ #include "absl/container/internal/node_slot_policy.h" #include "absl/container/internal/raw_hash_map.h" // IWYU pragma: export #include "absl/memory/memory.h" +#include "absl/meta/type_traits.h" namespace absl { ABSL_NAMESPACE_BEGIN @@ -559,6 +560,38 @@ typename node_hash_map<K, V, H, E, A>::size_type erase_if( namespace container_internal { +// c_for_each_fast(node_hash_map<>, Function) +// +// Container-based version of the <algorithm> `std::for_each()` function to +// apply a function to a container's elements. +// There is no guarantees on the order of the function calls. +// Erasure and/or insertion of elements in the function is not allowed. +template <typename K, typename V, typename H, typename E, typename A, + typename Function> +decay_t<Function> c_for_each_fast(const node_hash_map<K, V, H, E, A>& c, + Function&& f) { + container_internal::ForEach(f, &c); + return f; +} +template <typename K, typename V, typename H, typename E, typename A, + typename Function> +decay_t<Function> c_for_each_fast(node_hash_map<K, V, H, E, A>& c, + Function&& f) { + container_internal::ForEach(f, &c); + return f; +} +template <typename K, typename V, typename H, typename E, typename A, + typename Function> +decay_t<Function> c_for_each_fast(node_hash_map<K, V, H, E, A>&& c, + Function&& f) { + container_internal::ForEach(f, &c); + return f; +} + +} // namespace container_internal + +namespace container_internal { + template <class Key, class Value> class NodeHashMapPolicy : public absl::container_internal::node_slot_policy< diff --git a/absl/container/node_hash_map_test.cc b/absl/container/node_hash_map_test.cc index 9bcf470c..2657828e 100644 --- a/absl/container/node_hash_map_test.cc +++ b/absl/container/node_hash_map_test.cc @@ -14,6 +14,18 @@ #include "absl/container/node_hash_map.h" +#include <cstddef> +#include <new> // NOLINT: used for __cpp_lib_launder +#include <string> +#include <tuple> +#include <type_traits> +#include <utility> +#include <vector> + +#include "gmock/gmock.h" +#include "gtest/gtest.h" +#include "absl/base/config.h" +#include "absl/container/internal/hash_policy_testing.h" #include "absl/container/internal/tracked.h" #include "absl/container/internal/unordered_map_constructor_test.h" #include "absl/container/internal/unordered_map_lookup_test.h" @@ -29,6 +41,7 @@ using ::testing::Field; using ::testing::IsEmpty; using ::testing::Pair; using ::testing::UnorderedElementsAre; +using ::testing::UnorderedElementsAreArray; using MapTypes = ::testing::Types< absl::node_hash_map<int, int, StatefulTestingHash, StatefulTestingEqual, @@ -257,6 +270,58 @@ TEST(NodeHashMap, EraseIf) { } } +TEST(NodeHashMap, CForEach) { + node_hash_map<int, int> m; + std::vector<std::pair<int, int>> expected; + for (int i = 0; i < 100; ++i) { + { + SCOPED_TRACE("mutable object iteration"); + std::vector<std::pair<int, int>> v; + absl::container_internal::c_for_each_fast( + m, [&v](std::pair<const int, int>& p) { v.push_back(p); }); + EXPECT_THAT(v, UnorderedElementsAreArray(expected)); + } + { + SCOPED_TRACE("const object iteration"); + std::vector<std::pair<int, int>> v; + const node_hash_map<int, int>& cm = m; + absl::container_internal::c_for_each_fast( + cm, [&v](const std::pair<const int, int>& p) { v.push_back(p); }); + EXPECT_THAT(v, UnorderedElementsAreArray(expected)); + } + { + SCOPED_TRACE("const object iteration"); + std::vector<std::pair<int, int>> v; + absl::container_internal::c_for_each_fast( + node_hash_map<int, int>(m), + [&v](std::pair<const int, int>& p) { v.push_back(p); }); + EXPECT_THAT(v, UnorderedElementsAreArray(expected)); + } + m[i] = i; + expected.emplace_back(i, i); + } +} + +TEST(NodeHashMap, CForEachMutate) { + node_hash_map<int, int> s; + std::vector<std::pair<int, int>> expected; + for (int i = 0; i < 100; ++i) { + std::vector<std::pair<int, int>> v; + absl::container_internal::c_for_each_fast( + s, [&v](std::pair<const int, int>& p) { + v.push_back(p); + p.second++; + }); + EXPECT_THAT(v, UnorderedElementsAreArray(expected)); + for (auto& p : expected) { + p.second++; + } + EXPECT_THAT(s, UnorderedElementsAreArray(expected)); + s[i] = i; + expected.emplace_back(i, i); + } +} + // This test requires std::launder for mutable key access in node handles. #if defined(__cpp_lib_launder) && __cpp_lib_launder >= 201606 TEST(NodeHashMap, NodeHandleMutableKeyAccess) { diff --git a/absl/container/node_hash_set.h b/absl/container/node_hash_set.h index 7228d192..53435ae6 100644 --- a/absl/container/node_hash_set.h +++ b/absl/container/node_hash_set.h @@ -48,6 +48,7 @@ #include "absl/container/internal/node_slot_policy.h" #include "absl/container/internal/raw_hash_set.h" // IWYU pragma: export #include "absl/memory/memory.h" +#include "absl/meta/type_traits.h" namespace absl { ABSL_NAMESPACE_BEGIN @@ -468,6 +469,33 @@ typename node_hash_set<T, H, E, A>::size_type erase_if( namespace container_internal { +// c_for_each_fast(node_hash_set<>, Function) +// +// Container-based version of the <algorithm> `std::for_each()` function to +// apply a function to a container's elements. +// There is no guarantees on the order of the function calls. +// Erasure and/or insertion of elements in the function is not allowed. +template <typename T, typename H, typename E, typename A, typename Function> +decay_t<Function> c_for_each_fast(const node_hash_set<T, H, E, A>& c, + Function&& f) { + container_internal::ForEach(f, &c); + return f; +} +template <typename T, typename H, typename E, typename A, typename Function> +decay_t<Function> c_for_each_fast(node_hash_set<T, H, E, A>& c, Function&& f) { + container_internal::ForEach(f, &c); + return f; +} +template <typename T, typename H, typename E, typename A, typename Function> +decay_t<Function> c_for_each_fast(node_hash_set<T, H, E, A>&& c, Function&& f) { + container_internal::ForEach(f, &c); + return f; +} + +} // namespace container_internal + +namespace container_internal { + template <class T> struct NodeHashSetPolicy : absl::container_internal::node_slot_policy<T&, NodeHashSetPolicy<T>> { diff --git a/absl/container/node_hash_set_test.cc b/absl/container/node_hash_set_test.cc index 98a8dbdd..e616ac1e 100644 --- a/absl/container/node_hash_set_test.cc +++ b/absl/container/node_hash_set_test.cc @@ -14,10 +14,22 @@ #include "absl/container/node_hash_set.h" +#include <cstddef> +#include <memory> +#include <string> +#include <utility> +#include <vector> + +#include "gmock/gmock.h" +#include "gtest/gtest.h" +#include "absl/base/config.h" +#include "absl/container/internal/hash_generator_testing.h" +#include "absl/container/internal/hash_policy_testing.h" #include "absl/container/internal/unordered_set_constructor_test.h" #include "absl/container/internal/unordered_set_lookup_test.h" #include "absl/container/internal/unordered_set_members_test.h" #include "absl/container/internal/unordered_set_modifiers_test.h" +#include "absl/memory/memory.h" namespace absl { ABSL_NAMESPACE_BEGIN @@ -28,6 +40,7 @@ using ::absl::container_internal::hash_internal::EnumClass; using ::testing::IsEmpty; using ::testing::Pointee; using ::testing::UnorderedElementsAre; +using ::testing::UnorderedElementsAreArray; using SetTypes = ::testing::Types< node_hash_set<int, StatefulTestingHash, StatefulTestingEqual, Alloc<int>>, @@ -137,6 +150,39 @@ TEST(NodeHashSet, EraseIf) { } } +TEST(NodeHashSet, CForEach) { + using ValueType = std::pair<int, int>; + node_hash_set<ValueType> s; + std::vector<ValueType> expected; + for (int i = 0; i < 100; ++i) { + { + SCOPED_TRACE("mutable object iteration"); + std::vector<ValueType> v; + absl::container_internal::c_for_each_fast( + s, [&v](const ValueType& p) { v.push_back(p); }); + ASSERT_THAT(v, UnorderedElementsAreArray(expected)); + } + { + SCOPED_TRACE("const object iteration"); + std::vector<ValueType> v; + const node_hash_set<ValueType>& cs = s; + absl::container_internal::c_for_each_fast( + cs, [&v](const ValueType& p) { v.push_back(p); }); + ASSERT_THAT(v, UnorderedElementsAreArray(expected)); + } + { + SCOPED_TRACE("temporary object iteration"); + std::vector<ValueType> v; + absl::container_internal::c_for_each_fast( + node_hash_set<ValueType>(s), + [&v](const ValueType& p) { v.push_back(p); }); + ASSERT_THAT(v, UnorderedElementsAreArray(expected)); + } + s.emplace(i, i); + expected.emplace_back(i, i); + } +} + } // namespace } // namespace container_internal ABSL_NAMESPACE_END |