On Mon, Aug 31, 2026 at 5:58 PM Marco Falke <[email protected]> wrote:
> libstdc++15 and 16 do not allow to construct an unordered set with a > hasher whose ctor is explicit. > > This is an issue with Clang, or with GCC -Wsystem-headers. See > https://godbolt.org/z/EGzKbjh84 > > Fix this by using value-init, similar to commit > f8f0193b5b83f6e85d65015e79c803295baf5166. However, that likely > regressed again in commit 689d4abc0b836aaf1c8ecd38091dde6b14373c60? > > patch is attached and copied later. > > I'd say the unit test could be expanded by adding > // { dg-additional-options "-Werror -Wsystem-headers" } > , but I wasn't sure if this is recommended. > > Best, Marco > > > > > From 2bd4a6218ff9ca10f1d11b6b19411c9556df90ed Mon Sep 17 00:00:00 2001 > From: MarcoFalke <[email protected]> > Date: Sun, 26 Jul 2026 14:30:58 +0000 > Subject: [PATCH] libstdc++: Value-initialize hashtable helper objects > [PR126949] > > Value-initialize the object stored in _Hashtable_ebo_helper so that hash > containers can be default constructed when the hash function has an > explicit default constructor. > > A default member initializer prevents aggregate initialization in C++11, > so add constructors that preserve initialization from hash, equality, and > allocator objects. > > libstdc++-v3/ChangeLog: > > PR libstdc++/126949 > * include/bits/hashtable_policy.h (_Hashtable_ebo_helper): > Value-initialize the stored object. Add default and forwarding > constructors. > * testsuite/23_containers/unordered_map/cons/default.cc: Check > default construction with an explicit hash constructor. > * testsuite/23_containers/unordered_set/cons/default.cc: Likewise. > --- > libstdc++-v3/include/bits/hashtable_policy.h | 18 ++++++++++++++++-- > .../unordered_map/cons/default.cc | 15 +++++++++++++++ > .../unordered_set/cons/default.cc | 15 +++++++++++++++ > 3 files changed, 46 insertions(+), 2 deletions(-) > > diff --git a/libstdc++-v3/include/bits/hashtable_policy.h > b/libstdc++-v3/include/bits/hashtable_policy.h > index 6e4b365d592..396214ed4bb 100644 > --- a/libstdc++-v3/include/bits/hashtable_policy.h > +++ b/libstdc++-v3/include/bits/hashtable_policy.h > @@ -1033,7 +1033,14 @@ namespace __detail > bool __use_ebo = !__is_final(_Tp) && __is_empty(_Tp)> > struct _Hashtable_ebo_helper > { > - [[__no_unique_address__]] _Tp _M_obj; > + [[__no_unique_address__]] _Tp _M_obj{}; > This is not value-initialization, but aggregate initialization (there are observable differences in corner cases). I would prefer that we actually use an value-init here and say = _Tp(). > + > + _Hashtable_ebo_helper() = default; > This constructor will no longer be trivial if the _Tp has trivial constructor, so I need to take a look to see if that may have ABI impact. > + > + template<typename _Up> > + _Hashtable_ebo_helper(_Up&& __obj) > + : _M_obj(std::forward<_Up>(__obj)) > + { } > }; > > #if ! _GLIBCXX_INLINE_VERSION > @@ -1042,7 +1049,14 @@ namespace __detail > template<typename _Tp> > struct _Hashtable_ebo_helper<_Tp, false> > { > - _Tp _M_obj; > + _Tp _M_obj{}; > + > + _Hashtable_ebo_helper() = default; > + > + template<typename _Up> > + _Hashtable_ebo_helper(_Up&& __obj) > + : _M_obj(std::forward<_Up>(__obj)) > + { } > }; > #endif > > diff --git > a/libstdc++-v3/testsuite/23_containers/unordered_map/cons/default.cc > b/libstdc++-v3/testsuite/23_containers/unordered_map/cons/default.cc > index 7a785e980b1..07089c36bcf 100644 > --- a/libstdc++-v3/testsuite/23_containers/unordered_map/cons/default.cc > +++ b/libstdc++-v3/testsuite/23_containers/unordered_map/cons/default.cc > @@ -49,3 +49,18 @@ Map4 m4{m}; > Map4 m5{m, a}; > Map4 m6{std::move(m)}; > Map4 m7{std::move(m6), a}; > + > +// PR libstdc++/126949 > +struct ExplicitHash > +{ > + explicit ExplicitHash(bool = false) { } > + > + std::size_t operator()(int value) const > + { return value; } > +}; > + > +void > +test_explicit_hash() > +{ > + std::unordered_map<int, int, ExplicitHash> map; > +} > diff --git > a/libstdc++-v3/testsuite/23_containers/unordered_set/cons/default.cc > b/libstdc++-v3/testsuite/23_containers/unordered_set/cons/default.cc > index fb87c96ce9d..8949b202125 100644 > --- a/libstdc++-v3/testsuite/23_containers/unordered_set/cons/default.cc > +++ b/libstdc++-v3/testsuite/23_containers/unordered_set/cons/default.cc > @@ -48,3 +48,18 @@ Set4 s4{s}; > Set4 s5{s, a}; > Set4 s6{std::move(s)}; > Set4 s7{std::move(s6), a}; > + > +// PR libstdc++/126949 > +struct ExplicitHash > +{ > + explicit ExplicitHash(bool = false) { } > + > + std::size_t operator()(int value) const > + { return value; } > +}; > + > +void > +test_explicit_hash() > +{ > + std::unordered_set<int, ExplicitHash> set; > +} > -- > 2.53.0 >
