summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Evan Brown <ezb@google.com>2024-03-12 14:29:39 -0700
committerGravatar Copybara-Service <copybara-worker@google.com>2024-03-12 14:31:30 -0700
commit038561296676d1cae4a3cee30f8c924befbb6083 (patch)
tree724042c21eb6dfc0913a1eff86ffc7da3e0f4274
parent3c1f9be71ee280539f02e57c5e461b0271f54e91 (diff)
Add extern templates for common swisstable types.
Motivation: mitigate linker input size increase from swisstable optimizations. Note: the changes in raw_hash_set.h are fixing build errors that happened when adding the explicit instantiations. The change in unchecked_deref is because set iterators have const reference access whereas map iterators have mutable reference access and the function is never actually called for sets (it's used in raw_hash_map) so it wasn't needed before. I'm not sure why the soo_slot/soo_iterator problems didn't cause compile errors earlier. PiperOrigin-RevId: 615174043 Change-Id: Iac5eb2332a76e9b70021156fbb2b8def47a5391d
-rw-r--r--CMake/AbseilDll.cmake4
-rw-r--r--absl/container/BUILD.bazel10
-rw-r--r--absl/container/CMakeLists.txt14
-rw-r--r--absl/container/flat_hash_map.cc40
-rw-r--r--absl/container/flat_hash_map.h41
-rw-r--r--absl/container/flat_hash_set.cc36
-rw-r--r--absl/container/flat_hash_set.h29
-rw-r--r--absl/container/internal/raw_hash_set.h32
-rw-r--r--absl/container/node_hash_map.cc40
-rw-r--r--absl/container/node_hash_map.h40
-rw-r--r--absl/container/node_hash_set.cc36
-rw-r--r--absl/container/node_hash_set.h30
12 files changed, 345 insertions, 7 deletions
diff --git a/CMake/AbseilDll.cmake b/CMake/AbseilDll.cmake
index 47f3beeb..4beafd7a 100644
--- a/CMake/AbseilDll.cmake
+++ b/CMake/AbseilDll.cmake
@@ -68,7 +68,9 @@ set(ABSL_INTERNAL_DLL_FILES
"container/btree_set.h"
"container/fixed_array.h"
"container/flat_hash_map.h"
+ "container/flat_hash_map.cc"
"container/flat_hash_set.h"
+ "container/flat_hash_set.cc"
"container/inlined_vector.h"
"container/internal/btree.h"
"container/internal/btree_container.h"
@@ -91,7 +93,9 @@ set(ABSL_INTERNAL_DLL_FILES
"container/internal/raw_hash_set.h"
"container/internal/tracked.h"
"container/node_hash_map.h"
+ "container/node_hash_map.cc"
"container/node_hash_set.h"
+ "container/node_hash_set.cc"
"crc/crc32c.cc"
"crc/crc32c.h"
"crc/internal/cpu_detect.cc"
diff --git a/absl/container/BUILD.bazel b/absl/container/BUILD.bazel
index 0de45263..366bf3cd 100644
--- a/absl/container/BUILD.bazel
+++ b/absl/container/BUILD.bazel
@@ -242,6 +242,7 @@ NOTEST_TAGS_MOBILE = [
cc_library(
name = "flat_hash_map",
+ srcs = ["flat_hash_map.cc"],
hdrs = ["flat_hash_map.h"],
copts = ABSL_DEFAULT_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
@@ -249,7 +250,9 @@ cc_library(
":container_memory",
":hash_function_defaults",
":raw_hash_map",
+ ":raw_hash_set",
"//absl/algorithm:container",
+ "//absl/base:config",
"//absl/base:core_headers",
"//absl/memory",
],
@@ -279,6 +282,7 @@ cc_test(
cc_library(
name = "flat_hash_set",
+ srcs = ["flat_hash_set.cc"],
hdrs = ["flat_hash_set.h"],
copts = ABSL_DEFAULT_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
@@ -287,6 +291,7 @@ cc_library(
":hash_function_defaults",
":raw_hash_set",
"//absl/algorithm:container",
+ "//absl/base:config",
"//absl/base:core_headers",
"//absl/memory",
],
@@ -318,6 +323,7 @@ cc_test(
cc_library(
name = "node_hash_map",
+ srcs = ["node_hash_map.cc"],
hdrs = ["node_hash_map.h"],
copts = ABSL_DEFAULT_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
@@ -326,7 +332,9 @@ cc_library(
":hash_function_defaults",
":node_slot_policy",
":raw_hash_map",
+ ":raw_hash_set",
"//absl/algorithm:container",
+ "//absl/base:config",
"//absl/base:core_headers",
"//absl/memory",
],
@@ -353,6 +361,7 @@ cc_test(
cc_library(
name = "node_hash_set",
+ srcs = ["node_hash_set.cc"],
hdrs = ["node_hash_set.h"],
copts = ABSL_DEFAULT_COPTS,
linkopts = ABSL_DEFAULT_LINKOPTS,
@@ -362,6 +371,7 @@ cc_library(
":node_slot_policy",
":raw_hash_set",
"//absl/algorithm:container",
+ "//absl/base:config",
"//absl/base:core_headers",
"//absl/memory",
],
diff --git a/absl/container/CMakeLists.txt b/absl/container/CMakeLists.txt
index 4b08e6a3..8e64adb1 100644
--- a/absl/container/CMakeLists.txt
+++ b/absl/container/CMakeLists.txt
@@ -283,13 +283,17 @@ absl_cc_library(
flat_hash_map
HDRS
"flat_hash_map.h"
+ SRCS
+ "flat_hash_map.cc"
COPTS
${ABSL_DEFAULT_COPTS}
DEPS
+ absl::config
absl::container_memory
absl::core_headers
absl::hash_function_defaults
absl::raw_hash_map
+ absl::raw_hash_set
absl::algorithm_container
absl::memory
PUBLIC
@@ -321,9 +325,12 @@ absl_cc_library(
flat_hash_set
HDRS
"flat_hash_set.h"
+ SRCS
+ "flat_hash_set.cc"
COPTS
${ABSL_DEFAULT_COPTS}
DEPS
+ absl::config
absl::container_memory
absl::hash_function_defaults
absl::raw_hash_set
@@ -362,14 +369,18 @@ absl_cc_library(
node_hash_map
HDRS
"node_hash_map.h"
+ SRCS
+ "node_hash_map.cc"
COPTS
${ABSL_DEFAULT_COPTS}
DEPS
+ absl::config
absl::container_memory
absl::core_headers
absl::hash_function_defaults
absl::node_slot_policy
absl::raw_hash_map
+ absl::raw_hash_set
absl::algorithm_container
absl::memory
PUBLIC
@@ -398,9 +409,12 @@ absl_cc_library(
node_hash_set
HDRS
"node_hash_set.h"
+ SRCS
+ "node_hash_set.cc"
COPTS
${ABSL_DEFAULT_COPTS}
DEPS
+ absl::config
absl::container_memory
absl::core_headers
absl::hash_function_defaults
diff --git a/absl/container/flat_hash_map.cc b/absl/container/flat_hash_map.cc
new file mode 100644
index 00000000..d5a25317
--- /dev/null
+++ b/absl/container/flat_hash_map.cc
@@ -0,0 +1,40 @@
+// Copyright 2024 The Abseil Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/container/flat_hash_map.h"
+
+#include <cstdint>
+#include <string>
+
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(template, int32_t, int32_t);
+ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(template, std::string, int32_t);
+ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(template, int32_t, std::string);
+ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(template, int64_t, int64_t);
+ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(template, std::string, int64_t);
+ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(template, int64_t, std::string);
+ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(template, uint32_t, uint32_t);
+ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(template, std::string, uint32_t);
+ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(template, uint32_t, std::string);
+ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(template, uint64_t, uint64_t);
+ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(template, std::string, uint64_t);
+ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(template, uint64_t, std::string);
+ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(template, std::string, std::string);
+
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/absl/container/flat_hash_map.h b/absl/container/flat_hash_map.h
index a33c794f..2f4457d6 100644
--- a/absl/container/flat_hash_map.h
+++ b/absl/container/flat_hash_map.h
@@ -31,15 +31,20 @@
#define ABSL_CONTAINER_FLAT_HASH_MAP_H_
#include <cstddef>
+#include <cstdint>
+#include <memory>
#include <new>
+#include <string>
#include <type_traits>
#include <utility>
#include "absl/algorithm/container.h"
+#include "absl/base/config.h"
#include "absl/base/macros.h"
#include "absl/container/internal/container_memory.h"
#include "absl/container/internal/hash_function_defaults.h" // IWYU pragma: export
#include "absl/container/internal/raw_hash_map.h" // IWYU pragma: export
+#include "absl/container/internal/raw_hash_set.h" // IWYU pragma: export
#include "absl/memory/memory.h"
namespace absl {
@@ -632,6 +637,42 @@ struct IsUnorderedContainer<
} // namespace container_algorithm_internal
+// Explicit template instantiations for common map types in order to decrease
+// linker input size. Note that explicitly instantiating flat_hash_map itself
+// doesn't help because it has no non-alias members. If we need to decrease
+// linker input size more, we could potentially (a) add more key/value types,
+// e.g. string_view/Cord, (b) instantiate some template member functions, e.g.
+// operator[]/find. The EXTERN argument is `extern` for the declaration and
+// empty for the definition.
+#define ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(TEMPLATE, KEY, VALUE) \
+ TEMPLATE class absl::container_internal::raw_hash_map< \
+ absl::container_internal::FlatHashMapPolicy<KEY, VALUE>, \
+ absl::container_internal::hash_default_hash<KEY>, \
+ absl::container_internal::hash_default_eq<KEY>, \
+ std::allocator<std::pair<const KEY, VALUE>>>; \
+ TEMPLATE class absl::container_internal::raw_hash_set< \
+ absl::container_internal::FlatHashMapPolicy<KEY, VALUE>, \
+ absl::container_internal::hash_default_hash<KEY>, \
+ absl::container_internal::hash_default_eq<KEY>, \
+ std::allocator<std::pair<const KEY, VALUE>>>;
+
+// We use exact-width integer types rather than `int`/`long`/`long long` because
+// these are the types recommended in the Google C++ style guide and which are
+// commonly used in Google code.
+ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(extern template, int32_t, int32_t);
+ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(extern template, std::string, int32_t);
+ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(extern template, int32_t, std::string);
+ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(extern template, int64_t, int64_t);
+ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(extern template, std::string, int64_t);
+ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(extern template, int64_t, std::string);
+ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(extern template, uint32_t, uint32_t);
+ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(extern template, std::string, uint32_t);
+ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(extern template, uint32_t, std::string);
+ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(extern template, uint64_t, uint64_t);
+ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(extern template, std::string, uint64_t);
+ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(extern template, uint64_t, std::string);
+ABSL_INTERNAL_TEMPLATE_FLAT_HASH_MAP(extern template, std::string, std::string);
+
ABSL_NAMESPACE_END
} // namespace absl
diff --git a/absl/container/flat_hash_set.cc b/absl/container/flat_hash_set.cc
new file mode 100644
index 00000000..d07081b8
--- /dev/null
+++ b/absl/container/flat_hash_set.cc
@@ -0,0 +1,36 @@
+// Copyright 2024 The Abseil Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/container/flat_hash_set.h"
+
+#include <cstdint>
+#include <string>
+
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+ABSL_INTERNAL_TEMPLATE_FLAT_HASH_SET(template, int8_t);
+ABSL_INTERNAL_TEMPLATE_FLAT_HASH_SET(template, int16_t);
+ABSL_INTERNAL_TEMPLATE_FLAT_HASH_SET(template, int32_t);
+ABSL_INTERNAL_TEMPLATE_FLAT_HASH_SET(template, int64_t);
+ABSL_INTERNAL_TEMPLATE_FLAT_HASH_SET(template, uint8_t);
+ABSL_INTERNAL_TEMPLATE_FLAT_HASH_SET(template, uint16_t);
+ABSL_INTERNAL_TEMPLATE_FLAT_HASH_SET(template, uint32_t);
+ABSL_INTERNAL_TEMPLATE_FLAT_HASH_SET(template, uint64_t);
+ABSL_INTERNAL_TEMPLATE_FLAT_HASH_SET(template, std::string);
+
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/absl/container/flat_hash_set.h b/absl/container/flat_hash_set.h
index 5f72f954..88c7ab21 100644
--- a/absl/container/flat_hash_set.h
+++ b/absl/container/flat_hash_set.h
@@ -30,11 +30,14 @@
#define ABSL_CONTAINER_FLAT_HASH_SET_H_
#include <cstddef>
+#include <cstdint>
#include <memory>
+#include <string>
#include <type_traits>
#include <utility>
#include "absl/algorithm/container.h"
+#include "absl/base/config.h"
#include "absl/base/macros.h"
#include "absl/container/internal/container_memory.h"
#include "absl/container/internal/hash_function_defaults.h" // IWYU pragma: export
@@ -523,6 +526,32 @@ struct IsUnorderedContainer<absl::flat_hash_set<Key, Hash, KeyEqual, Allocator>>
} // namespace container_algorithm_internal
+// Explicit template instantiations for common set types in order to decrease
+// linker input size. Note that explicitly instantiating flat_hash_set itself
+// doesn't help because it has no non-alias members. If we need to decrease
+// linker input size more, we could potentially (a) add more key types, e.g.
+// string_view/Cord, (b) instantiate some template member functions, e.g.
+// find/insert/emplace. The EXTERN argument is `extern` for the declaration and
+// empty for the definition.
+#define ABSL_INTERNAL_TEMPLATE_FLAT_HASH_SET(TEMPLATE, KEY) \
+ TEMPLATE class absl::container_internal::raw_hash_set< \
+ absl::container_internal::FlatHashSetPolicy<KEY>, \
+ absl::container_internal::hash_default_hash<KEY>, \
+ absl::container_internal::hash_default_eq<KEY>, std::allocator<KEY>>;
+
+// We use exact-width integer types rather than `int`/`long`/`long long` because
+// these are the types recommended in the Google C++ style guide and which are
+// commonly used in Google code.
+ABSL_INTERNAL_TEMPLATE_FLAT_HASH_SET(extern template, int8_t);
+ABSL_INTERNAL_TEMPLATE_FLAT_HASH_SET(extern template, int16_t);
+ABSL_INTERNAL_TEMPLATE_FLAT_HASH_SET(extern template, int32_t);
+ABSL_INTERNAL_TEMPLATE_FLAT_HASH_SET(extern template, int64_t);
+ABSL_INTERNAL_TEMPLATE_FLAT_HASH_SET(extern template, uint8_t);
+ABSL_INTERNAL_TEMPLATE_FLAT_HASH_SET(extern template, uint16_t);
+ABSL_INTERNAL_TEMPLATE_FLAT_HASH_SET(extern template, uint32_t);
+ABSL_INTERNAL_TEMPLATE_FLAT_HASH_SET(extern template, uint64_t);
+ABSL_INTERNAL_TEMPLATE_FLAT_HASH_SET(extern template, std::string);
+
ABSL_NAMESPACE_END
} // namespace absl
diff --git a/absl/container/internal/raw_hash_set.h b/absl/container/internal/raw_hash_set.h
index 258458b0..575491c7 100644
--- a/absl/container/internal/raw_hash_set.h
+++ b/absl/container/internal/raw_hash_set.h
@@ -1839,7 +1839,7 @@ class HashSetResizeHelper {
// Reads `capacity` and updates all other fields based on the result of
// the allocation.
//
- // It also may do the folowing actions:
+ // It also may do the following actions:
// 1. initialize control bytes
// 2. initialize slots
// 3. deallocate old slots.
@@ -2204,9 +2204,14 @@ class raw_hash_set {
bool is_soo() const { return fits_in_soo(capacity()); }
bool is_full_soo() const { return is_soo() && !empty(); }
- // Give an early error when key_type is not hashable/eq.
- auto KeyTypeCanBeHashed(const Hash& h, const key_type& k) -> decltype(h(k));
- auto KeyTypeCanBeEq(const Eq& eq, const key_type& k) -> decltype(eq(k, k));
+ // Give an early error when key_type is not hashable/eq. Definitions are
+ // provided because otherwise explicit template instantiation fails on MSVC.
+ auto KeyTypeCanBeHashed(const Hash& h, const key_type& k) -> decltype(h(k)) {
+ ABSL_UNREACHABLE();
+ }
+ auto KeyTypeCanBeEq(const Eq& eq, const key_type& k) -> decltype(eq(k, k)) {
+ ABSL_UNREACHABLE();
+ }
using AllocTraits = absl::allocator_traits<allocator_type>;
using SlotAlloc = typename absl::allocator_traits<
@@ -2395,7 +2400,18 @@ class raw_hash_set {
const_iterator operator++(int) { return inner_++; }
friend bool operator==(const const_iterator& a, const const_iterator& b) {
+ // Suppress erroneous uninitialized memory errors on GCC. This seems to be
+ // because the slot pointer in the inner_ iterator is uninitialized, even
+ // though that pointer is not used when uninitialized.
+ // Similar bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=112637.
+#if !defined(__clang__) && defined(__GNUC__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
+#endif
return a.inner_ == b.inner_;
+#if !defined(__clang__) && defined(__GNUC__)
+#pragma GCC diagnostic pop
+#endif
}
friend bool operator!=(const const_iterator& a, const const_iterator& b) {
return !(a == b);
@@ -3719,7 +3735,9 @@ class raw_hash_set {
return const_cast<raw_hash_set*>(this)->iterator_at(i);
}
- reference unchecked_deref(iterator it) { return it.unchecked_deref(); }
+ reference unchecked_deref(iterator it) {
+ return const_cast<reference>(it.unchecked_deref());
+ }
private:
friend struct RawHashSetTestOnlyAccess;
@@ -3769,13 +3787,13 @@ class raw_hash_set {
return static_cast<slot_type*>(common().soo_data());
}
const slot_type* soo_slot() const {
- return reinterpret_cast<raw_hash_set*>(this)->soo_slot();
+ return const_cast<raw_hash_set*>(this)->soo_slot();
}
iterator soo_iterator() {
return {SooControl(), soo_slot(), common().generation_ptr()};
}
const_iterator soo_iterator() const {
- return reinterpret_cast<raw_hash_set*>(this)->soo_iterator();
+ return const_cast<raw_hash_set*>(this)->soo_iterator();
}
HashtablezInfoHandle infoz() {
assert(!is_soo());
diff --git a/absl/container/node_hash_map.cc b/absl/container/node_hash_map.cc
new file mode 100644
index 00000000..ccf8c599
--- /dev/null
+++ b/absl/container/node_hash_map.cc
@@ -0,0 +1,40 @@
+// Copyright 2024 The Abseil Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/container/node_hash_map.h"
+
+#include <cstdint>
+#include <string>
+
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(template, int32_t, int32_t);
+ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(template, std::string, int32_t);
+ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(template, int32_t, std::string);
+ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(template, int64_t, int64_t);
+ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(template, std::string, int64_t);
+ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(template, int64_t, std::string);
+ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(template, uint32_t, uint32_t);
+ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(template, std::string, uint32_t);
+ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(template, uint32_t, std::string);
+ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(template, uint64_t, uint64_t);
+ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(template, std::string, uint64_t);
+ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(template, uint64_t, std::string);
+ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(template, std::string, std::string);
+
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/absl/container/node_hash_map.h b/absl/container/node_hash_map.h
index cb41543c..acc21542 100644
--- a/absl/container/node_hash_map.h
+++ b/absl/container/node_hash_map.h
@@ -37,11 +37,15 @@
#define ABSL_CONTAINER_NODE_HASH_MAP_H_
#include <cstddef>
+#include <cstdint>
+#include <memory>
+#include <string>
#include <tuple>
#include <type_traits>
#include <utility>
#include "absl/algorithm/container.h"
+#include "absl/base/config.h"
#include "absl/base/macros.h"
#include "absl/container/internal/container_memory.h"
#include "absl/container/internal/hash_function_defaults.h" // IWYU pragma: export
@@ -623,6 +627,42 @@ struct IsUnorderedContainer<
} // namespace container_algorithm_internal
+// Explicit template instantiations for common map types in order to decrease
+// linker input size. Note that explicitly instantiating node_hash_map itself
+// doesn't help because it has no non-alias members. If we need to decrease
+// linker input size more, we could potentially (a) add more key/value types,
+// e.g. string_view/Cord, (b) instantiate some template member functions, e.g.
+// operator[]/find. The EXTERN argument is `extern` for the declaration and
+// empty for the definition.
+#define ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(TEMPLATE, KEY, VALUE) \
+ TEMPLATE class absl::container_internal::raw_hash_map< \
+ absl::container_internal::NodeHashMapPolicy<KEY, VALUE>, \
+ absl::container_internal::hash_default_hash<KEY>, \
+ absl::container_internal::hash_default_eq<KEY>, \
+ std::allocator<std::pair<const KEY, VALUE>>>; \
+ TEMPLATE class absl::container_internal::raw_hash_set< \
+ absl::container_internal::NodeHashMapPolicy<KEY, VALUE>, \
+ absl::container_internal::hash_default_hash<KEY>, \
+ absl::container_internal::hash_default_eq<KEY>, \
+ std::allocator<std::pair<const KEY, VALUE>>>;
+
+// We use exact-width integer types rather than `int`/`long`/`long long` because
+// these are the types recommended in the Google C++ style guide and which are
+// commonly used in Google code.
+ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(extern template, int32_t, int32_t);
+ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(extern template, std::string, int32_t);
+ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(extern template, int32_t, std::string);
+ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(extern template, int64_t, int64_t);
+ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(extern template, std::string, int64_t);
+ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(extern template, int64_t, std::string);
+ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(extern template, uint32_t, uint32_t);
+ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(extern template, std::string, uint32_t);
+ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(extern template, uint32_t, std::string);
+ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(extern template, uint64_t, uint64_t);
+ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(extern template, std::string, uint64_t);
+ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(extern template, uint64_t, std::string);
+ABSL_INTERNAL_TEMPLATE_NODE_HASH_MAP(extern template, std::string, std::string);
+
ABSL_NAMESPACE_END
} // namespace absl
diff --git a/absl/container/node_hash_set.cc b/absl/container/node_hash_set.cc
new file mode 100644
index 00000000..39226c61
--- /dev/null
+++ b/absl/container/node_hash_set.cc
@@ -0,0 +1,36 @@
+// Copyright 2024 The Abseil Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// https://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "absl/container/node_hash_set.h"
+
+#include <cstdint>
+#include <string>
+
+#include "absl/base/config.h"
+
+namespace absl {
+ABSL_NAMESPACE_BEGIN
+
+ABSL_INTERNAL_TEMPLATE_NODE_HASH_SET(template, int8_t);
+ABSL_INTERNAL_TEMPLATE_NODE_HASH_SET(template, int16_t);
+ABSL_INTERNAL_TEMPLATE_NODE_HASH_SET(template, int32_t);
+ABSL_INTERNAL_TEMPLATE_NODE_HASH_SET(template, int64_t);
+ABSL_INTERNAL_TEMPLATE_NODE_HASH_SET(template, uint8_t);
+ABSL_INTERNAL_TEMPLATE_NODE_HASH_SET(template, uint16_t);
+ABSL_INTERNAL_TEMPLATE_NODE_HASH_SET(template, uint32_t);
+ABSL_INTERNAL_TEMPLATE_NODE_HASH_SET(template, uint64_t);
+ABSL_INTERNAL_TEMPLATE_NODE_HASH_SET(template, std::string);
+
+ABSL_NAMESPACE_END
+} // namespace absl
diff --git a/absl/container/node_hash_set.h b/absl/container/node_hash_set.h
index 8cc4b624..77b49f9b 100644
--- a/absl/container/node_hash_set.h
+++ b/absl/container/node_hash_set.h
@@ -36,9 +36,13 @@
#define ABSL_CONTAINER_NODE_HASH_SET_H_
#include <cstddef>
+#include <cstdint>
+#include <memory>
+#include <string>
#include <type_traits>
#include "absl/algorithm/container.h"
+#include "absl/base/config.h"
#include "absl/base/macros.h"
#include "absl/container/internal/container_memory.h"
#include "absl/container/internal/hash_function_defaults.h" // IWYU pragma: export
@@ -518,6 +522,32 @@ struct IsUnorderedContainer<absl::node_hash_set<Key, Hash, KeyEqual, Allocator>>
: std::true_type {};
} // namespace container_algorithm_internal
+
+// Explicit template instantiations for common set types in order to decrease
+// linker input size. Note that explicitly instantiating node_hash_set itself
+// doesn't help because it has no non-alias members. If we need to decrease
+// linker input size more, we could potentially (a) add more key types, e.g.
+// string_view/Cord, (b) instantiate some template member functions, e.g.
+// find/insert/emplace.
+#define ABSL_INTERNAL_TEMPLATE_NODE_HASH_SET(TEMPLATE, KEY) \
+ TEMPLATE class absl::container_internal::raw_hash_set< \
+ absl::container_internal::NodeHashSetPolicy<KEY>, \
+ absl::container_internal::hash_default_hash<KEY>, \
+ absl::container_internal::hash_default_eq<KEY>, std::allocator<KEY>>;
+
+// We use exact-width integer types rather than `int`/`long`/`long long` because
+// these are the types recommended in the Google C++ style guide and which are
+// commonly used in Google code.
+ABSL_INTERNAL_TEMPLATE_NODE_HASH_SET(extern template, int8_t);
+ABSL_INTERNAL_TEMPLATE_NODE_HASH_SET(extern template, int16_t);
+ABSL_INTERNAL_TEMPLATE_NODE_HASH_SET(extern template, int32_t);
+ABSL_INTERNAL_TEMPLATE_NODE_HASH_SET(extern template, int64_t);
+ABSL_INTERNAL_TEMPLATE_NODE_HASH_SET(extern template, uint8_t);
+ABSL_INTERNAL_TEMPLATE_NODE_HASH_SET(extern template, uint16_t);
+ABSL_INTERNAL_TEMPLATE_NODE_HASH_SET(extern template, uint32_t);
+ABSL_INTERNAL_TEMPLATE_NODE_HASH_SET(extern template, uint64_t);
+ABSL_INTERNAL_TEMPLATE_NODE_HASH_SET(extern template, std::string);
+
ABSL_NAMESPACE_END
} // namespace absl