Construct {flat,node}_hash_{set,map} w/ from_range
Adds constructors accepting std::from_range if building with C++23. See https://en.cppreference.com/w/cpp/ranges/from_range.html for context.
PiperOrigin-RevId: 867742476
Change-Id: I9ab07e772477bcc29fff438903b90945b89c5a1f
diff --git a/absl/container/flat_hash_map.h b/absl/container/flat_hash_map.h
index 7ce3353..1677f6a 100644
--- a/absl/container/flat_hash_map.h
+++ b/absl/container/flat_hash_map.h
@@ -181,6 +181,11 @@
//
// std::vector<std::pair<int, std::string>> v = {{1, "a"}, {2, "b"}};
// absl::flat_hash_map<int, std::string> map7(v.begin(), v.end());
+ //
+ // * from_range constructor (C++23)
+ //
+ // std::vector<std::pair<int, std::string>> v = {{1, "a"}, {2, "b"}};
+ // absl::flat_hash_map<int, std::string> map8(std::from_range, v);
flat_hash_map() {}
using Base::Base;
diff --git a/absl/container/flat_hash_map_test.cc b/absl/container/flat_hash_map_test.cc
index 73f28c7..a4efb7d 100644
--- a/absl/container/flat_hash_map_test.cc
+++ b/absl/container/flat_hash_map_test.cc
@@ -35,6 +35,10 @@
#include "absl/meta/type_traits.h"
#include "absl/types/any.h"
+#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
+#include <ranges> // NOLINT(build/c++20)
+#endif
+
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace container_internal {
@@ -445,6 +449,36 @@
EXPECT_DEATH_IF_SUPPORTED(insert_conflicting_elems(), crash_message);
}
+#if defined(__cpp_lib_containers_ranges) && \
+ __cpp_lib_containers_ranges >= 202202L
+TEST(FlatHashMap, FromRange) {
+ std::vector<std::pair<int, int>> v = {{1, 2}, {3, 4}, {5, 6}};
+ absl::flat_hash_map<int, int> m(std::from_range, v);
+ EXPECT_THAT(m, UnorderedElementsAre(Pair(1, 2), Pair(3, 4), Pair(5, 6)));
+}
+
+TEST(FlatHashMap, FromRangeWithAllocator) {
+ std::vector<std::pair<int, int>> v = {{1, 2}, {3, 4}, {5, 6}};
+ absl::flat_hash_map<int, int,
+ absl::container_internal::hash_default_hash<int>,
+ absl::container_internal::hash_default_eq<int>,
+ Alloc<std::pair<const int, int>>>
+ m(std::from_range, v, 0, Alloc<std::pair<const int, int>>());
+ EXPECT_THAT(m, UnorderedElementsAre(Pair(1, 2), Pair(3, 4), Pair(5, 6)));
+}
+
+TEST(FlatHashMap, FromRangeWithHasherAndAllocator) {
+ std::vector<std::pair<int, int>> v = {{1, 2}, {3, 4}, {5, 6}};
+ using TestingHash = absl::container_internal::StatefulTestingHash;
+ absl::flat_hash_map<int, int, TestingHash,
+ absl::container_internal::hash_default_eq<int>,
+ Alloc<std::pair<const int, int>>>
+ m(std::from_range, v, 0, TestingHash{},
+ Alloc<std::pair<const int, int>>());
+ EXPECT_THAT(m, UnorderedElementsAre(Pair(1, 2), Pair(3, 4), Pair(5, 6)));
+}
+#endif
+
} // namespace
} // namespace container_internal
ABSL_NAMESPACE_END
diff --git a/absl/container/flat_hash_set.h b/absl/container/flat_hash_set.h
index a469fa0..f802057 100644
--- a/absl/container/flat_hash_set.h
+++ b/absl/container/flat_hash_set.h
@@ -177,6 +177,11 @@
//
// std::vector<std::string> v = {"a", "b"};
// absl::flat_hash_set<std::string> set7(v.begin(), v.end());
+ //
+ // * from_range constructor (C++23)
+ //
+ // std::vector<std::string> v = {"a", "b"};
+ // absl::flat_hash_set<std::string> set8(std::from_range, v);
flat_hash_set() {}
using Base::Base;
diff --git a/absl/container/flat_hash_set_test.cc b/absl/container/flat_hash_set_test.cc
index 9b6a6d1..f776f38 100644
--- a/absl/container/flat_hash_set_test.cc
+++ b/absl/container/flat_hash_set_test.cc
@@ -38,6 +38,10 @@
#include "absl/memory/memory.h"
#include "absl/strings/string_view.h"
+#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
+#include <ranges> // NOLINT(build/c++20)
+#endif
+
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace container_internal {
@@ -395,6 +399,34 @@
false);
}
+#if defined(__cpp_lib_containers_ranges) && \
+ __cpp_lib_containers_ranges >= 202202L
+TEST(FlatHashSet, FromRange) {
+ std::vector<int> v = {1, 2, 3, 4, 5};
+ absl::flat_hash_set<int> s(std::from_range, v);
+ EXPECT_THAT(s, UnorderedElementsAre(1, 2, 3, 4, 5));
+}
+
+TEST(FlatHashSet, FromRangeWithAllocator) {
+ std::vector<int> v = {1, 2, 3, 4, 5};
+ absl::flat_hash_set<int, absl::container_internal::hash_default_hash<int>,
+ absl::container_internal::hash_default_eq<int>,
+ Alloc<int>>
+ s(std::from_range, v, 0, Alloc<int>());
+ EXPECT_THAT(s, UnorderedElementsAre(1, 2, 3, 4, 5));
+}
+
+TEST(FlatHashSet, FromRangeWithHasherAndAllocator) {
+ std::vector<int> v = {1, 2, 3, 4, 5};
+ using TestingHash = absl::container_internal::StatefulTestingHash;
+ absl::flat_hash_set<int, TestingHash,
+ absl::container_internal::hash_default_eq<int>,
+ Alloc<int>>
+ s(std::from_range, v, 0, TestingHash{}, Alloc<int>());
+ EXPECT_THAT(s, UnorderedElementsAre(1, 2, 3, 4, 5));
+}
+#endif
+
} // namespace
} // namespace container_internal
ABSL_NAMESPACE_END
diff --git a/absl/container/internal/raw_hash_set.h b/absl/container/internal/raw_hash_set.h
index d307e2d..a123ebd 100644
--- a/absl/container/internal/raw_hash_set.h
+++ b/absl/container/internal/raw_hash_set.h
@@ -221,6 +221,10 @@
#include "absl/numeric/bits.h"
#include "absl/utility/utility.h"
+#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
+#include <ranges> // NOLINT(build/c++20)
+#endif
+
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace container_internal {
@@ -2149,6 +2153,28 @@
const allocator_type& alloc)
: raw_hash_set(first, last, bucket_count, hasher(), key_equal(), alloc) {}
+#if defined(__cpp_lib_containers_ranges) && \
+ __cpp_lib_containers_ranges >= 202202L
+ template <typename R>
+ raw_hash_set(std::from_range_t, R&& rg, size_type bucket_count = 0,
+ const hasher& hash = hasher(), const key_equal& eq = key_equal(),
+ const allocator_type& alloc = allocator_type())
+ : raw_hash_set(std::begin(rg), std::end(rg), bucket_count, hash, eq,
+ alloc) {}
+
+ template <typename R>
+ raw_hash_set(std::from_range_t, R&& rg, size_type bucket_count,
+ const allocator_type& alloc)
+ : raw_hash_set(std::from_range, std::forward<R>(rg), bucket_count,
+ hasher(), key_equal(), alloc) {}
+
+ template <typename R>
+ raw_hash_set(std::from_range_t, R&& rg, size_type bucket_count,
+ const hasher& hash, const allocator_type& alloc)
+ : raw_hash_set(std::from_range, std::forward<R>(rg), bucket_count, hash,
+ key_equal(), alloc) {}
+#endif
+
template <class InputIter>
raw_hash_set(InputIter first, InputIter last, const allocator_type& alloc)
: raw_hash_set(first, last, 0, hasher(), key_equal(), alloc) {}
diff --git a/absl/container/node_hash_map.h b/absl/container/node_hash_map.h
index 580a044..3ceef32 100644
--- a/absl/container/node_hash_map.h
+++ b/absl/container/node_hash_map.h
@@ -177,6 +177,11 @@
//
// std::vector<std::pair<int, std::string>> v = {{1, "a"}, {2, "b"}};
// absl::node_hash_map<int, std::string> map7(v.begin(), v.end());
+ //
+ // * from_range constructor (C++23)
+ //
+ // std::vector<std::pair<int, std::string>> v = {{1, "a"}, {2, "b"}};
+ // absl::node_hash_map<int, std::string> map8(std::from_range, v);
node_hash_map() {}
using Base::Base;
diff --git a/absl/container/node_hash_map_test.cc b/absl/container/node_hash_map_test.cc
index c67d81f..6e92bbe 100644
--- a/absl/container/node_hash_map_test.cc
+++ b/absl/container/node_hash_map_test.cc
@@ -32,6 +32,10 @@
#include "absl/container/internal/unordered_map_members_test.h"
#include "absl/container/internal/unordered_map_modifiers_test.h"
+#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
+#include <ranges> // NOLINT(build/c++20)
+#endif
+
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace container_internal {
@@ -342,6 +346,36 @@
t.m[0] = RecursiveType{};
}
+#if defined(__cpp_lib_containers_ranges) && \
+ __cpp_lib_containers_ranges >= 202202L
+TEST(NodeHashMap, FromRange) {
+ std::vector<std::pair<int, int>> v = {{1, 2}, {3, 4}, {5, 6}};
+ absl::node_hash_map<int, int> m(std::from_range, v);
+ EXPECT_THAT(m, UnorderedElementsAre(Pair(1, 2), Pair(3, 4), Pair(5, 6)));
+}
+
+TEST(NodeHashMap, FromRangeWithAllocator) {
+ std::vector<std::pair<int, int>> v = {{1, 2}, {3, 4}, {5, 6}};
+ absl::node_hash_map<int, int,
+ absl::container_internal::hash_default_hash<int>,
+ absl::container_internal::hash_default_eq<int>,
+ Alloc<std::pair<const int, int>>>
+ m(std::from_range, v, 0, Alloc<std::pair<const int, int>>());
+ EXPECT_THAT(m, UnorderedElementsAre(Pair(1, 2), Pair(3, 4), Pair(5, 6)));
+}
+
+TEST(NodeHashMap, FromRangeWithHasherAndAllocator) {
+ std::vector<std::pair<int, int>> v = {{1, 2}, {3, 4}, {5, 6}};
+ using TestingHash = absl::container_internal::StatefulTestingHash;
+ absl::node_hash_map<int, int, TestingHash,
+ absl::container_internal::hash_default_eq<int>,
+ Alloc<std::pair<const int, int>>>
+ m(std::from_range, v, 0, TestingHash{},
+ Alloc<std::pair<const int, int>>());
+ EXPECT_THAT(m, UnorderedElementsAre(Pair(1, 2), Pair(3, 4), Pair(5, 6)));
+}
+#endif
+
} // namespace
} // namespace container_internal
ABSL_NAMESPACE_END
diff --git a/absl/container/node_hash_set.h b/absl/container/node_hash_set.h
index f69c6ab..17aa763 100644
--- a/absl/container/node_hash_set.h
+++ b/absl/container/node_hash_set.h
@@ -171,6 +171,11 @@
//
// std::vector<std::string> v = {"a", "b"};
// absl::node_hash_set<std::string> set7(v.begin(), v.end());
+ //
+ // * from_range constructor (C++23)
+ //
+ // std::vector<std::string> v = {"a", "b"};
+ // absl::node_hash_set<std::string> set8(std::from_range, v);
node_hash_set() {}
using Base::Base;
diff --git a/absl/container/node_hash_set_test.cc b/absl/container/node_hash_set_test.cc
index e1f5bd9..b29d0ca 100644
--- a/absl/container/node_hash_set_test.cc
+++ b/absl/container/node_hash_set_test.cc
@@ -31,6 +31,10 @@
#include "absl/container/internal/unordered_set_modifiers_test.h"
#include "absl/memory/memory.h"
+#if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
+#include <ranges> // NOLINT(build/c++20)
+#endif
+
namespace absl {
ABSL_NAMESPACE_BEGIN
namespace container_internal {
@@ -182,6 +186,34 @@
}
}
+#if defined(__cpp_lib_containers_ranges) && \
+ __cpp_lib_containers_ranges >= 202202L
+TEST(NodeHashSet, FromRange) {
+ std::vector<int> v = {1, 2, 3, 4, 5};
+ absl::node_hash_set<int> s(std::from_range, v);
+ EXPECT_THAT(s, UnorderedElementsAre(1, 2, 3, 4, 5));
+}
+
+TEST(NodeHashSet, FromRangeWithAllocator) {
+ std::vector<int> v = {1, 2, 3, 4, 5};
+ absl::node_hash_set<int, absl::container_internal::hash_default_hash<int>,
+ absl::container_internal::hash_default_eq<int>,
+ Alloc<int>>
+ s(std::from_range, v, 0, Alloc<int>());
+ EXPECT_THAT(s, UnorderedElementsAre(1, 2, 3, 4, 5));
+}
+
+TEST(NodeHashSet, FromRangeWithHasherAndAllocator) {
+ std::vector<int> v = {1, 2, 3, 4, 5};
+ using TestingHash = absl::container_internal::StatefulTestingHash;
+ absl::node_hash_set<int, TestingHash,
+ absl::container_internal::hash_default_eq<int>,
+ Alloc<int>>
+ s(std::from_range, v, 0, TestingHash{}, Alloc<int>());
+ EXPECT_THAT(s, UnorderedElementsAre(1, 2, 3, 4, 5));
+}
+#endif
+
} // namespace
} // namespace container_internal
ABSL_NAMESPACE_END