The __is_key_type specialization that matches a pair<key_type, T> argument is intended for std::unordered_map, not for std::unordered_set<std::pair<K,T>>.
This uses a pair<const Args&...> as the template argument for __is_key_type, so that it won't match a set's key_type. libstdc++-v3/ChangeLog: PR libstdc++/117686 * include/bits/hashtable.h (_Hashtable::_M_emplace_uniq): Adjust usage of __is_key_type to avoid false positive. * testsuite/23_containers/unordered_set/insert/117686.cc: New test. --- Tested powerpc64le-linux. Pushed to trunk. libstdc++-v3/include/bits/hashtable.h | 4 ++-- .../23_containers/unordered_set/insert/117686.cc | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 libstdc++-v3/testsuite/23_containers/unordered_set/insert/117686.cc diff --git a/libstdc++-v3/include/bits/hashtable.h b/libstdc++-v3/include/bits/hashtable.h index a704816573a..b8bd8c2f418 100644 --- a/libstdc++-v3/include/bits/hashtable.h +++ b/libstdc++-v3/include/bits/hashtable.h @@ -2286,9 +2286,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } else if constexpr (sizeof...(_Args) == 2) { - pair<const _Args&...> __refs(__args...); - if constexpr (__is_key_type<pair<_Args...>>) + if constexpr (__is_key_type<pair<const _Args&...>>) { + pair<const _Args&...> __refs(__args...); const auto& __key = _ExtractKey{}(__refs); __kp = std::__addressof(__key); } diff --git a/libstdc++-v3/testsuite/23_containers/unordered_set/insert/117686.cc b/libstdc++-v3/testsuite/23_containers/unordered_set/insert/117686.cc new file mode 100644 index 00000000000..3baac16c2b4 --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/unordered_set/insert/117686.cc @@ -0,0 +1,16 @@ +// { dg-do compile { target c++11 } } +// Bug 117686 - error in unordered_set::emplace + +#include <unordered_set> +#include <utility> + +struct H { + std::size_t operator()(const std::pair<int, int>&) const { return 0; } +}; + +void +test_117686() +{ + std::unordered_set<std::pair<int, int>, H> s; + s.emplace(1, 2); +} -- 2.47.0