On Thu, 12 Feb 2026 at 18:12, Nathan Myers <[email protected]> wrote:
>
> Changes in v2:
>  - Fix numerous errors revealed by actual testing.
>  - Delete excess overloads in unordered_multimap and
>   unordered_multiset.
>
> Implement the debug versions of new overloads from P2363.
>
> Also, simplify implementation of other overloads to match.
>
> libstdc++-v3/ChangeLog:
>         PR libstdc++/117402
>         * include/debug/map.h (try_emplace (2x), insert_or_assign (2x)):
>         Define heterogeneous overloads, simplify existing overloads.
>         * include/debug/unordered_map: Same.
>         * include/debug/set.h (insert (2x)):
>         Define heterogeneous overloads.
>         * include/debug/unordered_set: Same.
> ---
>  libstdc++-v3/include/debug/map.h         | 83 +++++++++++++++++-------
>  libstdc++-v3/include/debug/set.h         | 21 ++++++
>  libstdc++-v3/include/debug/unordered_map | 64 +++++++++++++++---
>  libstdc++-v3/include/debug/unordered_set | 26 ++++++++
>  4 files changed, 161 insertions(+), 33 deletions(-)
>
> diff --git a/libstdc++-v3/include/debug/map.h 
> b/libstdc++-v3/include/debug/map.h
> index 0fc7afae385..d6d2600d904 100644
> --- a/libstdc++-v3/include/debug/map.h
> +++ b/libstdc++-v3/include/debug/map.h
> @@ -382,18 +382,26 @@ namespace __debug
>           return { { __res.first, this }, __res.second };
>         }
>
> +# ifdef __glibcxx_associative_heterogeneous_insertion
> +      template <__heterogeneous_tree_key<map> _Kt, typename... _Args>
> +       pair<iterator, bool>
> +       try_emplace(_Kt&& __k, _Args&&... __args)
> +       {
> +         auto __res = _Base::try_emplace(
> +           std::forward<_Kt>(__k), std::forward<_Args>(__args)...);
> +         return { { __res.first, this }, __res.second };
> +       }
> +#endif
> +
>        template <typename... _Args>
>          iterator
>          try_emplace(const_iterator __hint, const key_type& __k,
>                      _Args&&... __args)
>          {
>           __glibcxx_check_insert(__hint);
> -         return
> -           {
> -             _Base::try_emplace(__hint.base(), __k,
> -                                std::forward<_Args>(__args)...),
> -             this
> -           };
> +         auto __it = _Base::try_emplace(__hint.base(), __k,
> +           std::forward<_Args>(__args)...);
> +         return { __it, this };
>         }
>
>        template <typename... _Args>
> @@ -401,14 +409,23 @@ namespace __debug
>          try_emplace(const_iterator __hint, key_type&& __k, _Args&&... __args)
>          {
>           __glibcxx_check_insert(__hint);
> -         return
> -           {
> -             _Base::try_emplace(__hint.base(), std::move(__k),
> -                                std::forward<_Args>(__args)...),
> -             this
> -           };
> +         auto __it = _Base::try_emplace(__hint.base(), std::move(__k),
> +           std::forward<_Args>(__args)...);
> +         return { __it, this };
>         }
>
> +# ifdef __glibcxx_associative_heterogeneous_insertion
> +      template <__heterogeneous_tree_key<map> _Kt, typename... _Args>
> +       iterator
> +       try_emplace(const_iterator __hint, _Kt&& __k, _Args&&... __args)
> +       {
> +         __glibcxx_check_insert(__hint);
> +         auto __it = _Base::try_emplace(__hint.base(),
> +           std::forward<_Kt>(__k), std::forward<_Args>(__args)...);
> +         return { __it, this };
> +       }
> +# endif
> +
>        template <typename _Obj>
>          std::pair<iterator, bool>
>          insert_or_assign(const key_type& __k, _Obj&& __obj)
> @@ -427,18 +444,26 @@ namespace __debug
>           return { { __res.first, this }, __res.second };
>         }
>
> +# ifdef __glibcxx_associative_heterogeneous_insertion
> +      template <__heterogeneous_tree_key<map> _Kt, typename _Obj>
> +       std::pair<iterator, bool>
> +       insert_or_assign(_Kt&& __k, _Obj&& __obj)
> +       {
> +         auto __res = _Base::insert_or_assign(
> +           std::forward<_Kt>(__k), std::forward<_Obj>(__obj));
> +         return { { __res.first, this }, __res.second };
> +       }
> +#endif
> +
>        template <typename _Obj>
>          iterator
>          insert_or_assign(const_iterator __hint,
>                           const key_type& __k, _Obj&& __obj)
>         {
>           __glibcxx_check_insert(__hint);
> -         return
> -           {
> -             _Base::insert_or_assign(__hint.base(), __k,
> -                                     std::forward<_Obj>(__obj)),
> -             this
> -           };
> +         auto __it = _Base::insert_or_assign(__hint.base(), __k,
> +           std::forward<_Obj>(__obj));
> +         return { __it, this };
>         }
>
>        template <typename _Obj>
> @@ -446,13 +471,23 @@ namespace __debug
>          insert_or_assign(const_iterator __hint, key_type&& __k, _Obj&& __obj)
>          {
>           __glibcxx_check_insert(__hint);
> -         return
> -           {
> -             _Base::insert_or_assign(__hint.base(), std::move(__k),
> -                                     std::forward<_Obj>(__obj)),
> -             this
> -           };
> +         auto __it = _Base::insert_or_assign(__hint.base(), std::move(__k),
> +           std::forward<_Obj>(__obj));
> +         return { __it, this };
>         }
> +
> +# ifdef __glibcxx_associative_heterogeneous_insertion
> +      template <__heterogeneous_tree_key<map> _Kt, typename _Obj>
> +       iterator
> +       insert_or_assign(const_iterator __hint, _Kt&& __k, _Obj&& __obj)
> +       {
> +         __glibcxx_check_insert(__hint);
> +         auto __it = _Base::insert_or_assign(__hint.base(),
> +           std::forward<_Kt>(__k), std::forward<_Obj>(__obj));
> +         return { __it, this };
> +       }
> +# endif
> +
>  #endif // C++17
>
>  #ifdef __glibcxx_node_extract // >= C++17 && HOSTED
> diff --git a/libstdc++-v3/include/debug/set.h 
> b/libstdc++-v3/include/debug/set.h
> index 99701d4a6d7..9180a87285b 100644
> --- a/libstdc++-v3/include/debug/set.h
> +++ b/libstdc++-v3/include/debug/set.h
> @@ -283,6 +283,16 @@ namespace __debug
>        }
>  #endif
>
> +#ifdef __glibcxx_associative_heterogeneous_insertion
> +      template <__heterogeneous_tree_key<set> _Kt>
> +       std::pair<iterator, bool>
> +       insert(_Kt&& __x)
> +       {
> +         auto __res = _Base::insert(std::forward<_Kt>(__x));
> +         return { { __res.first, this }, __res.second };
> +       }
> +#endif
> +
>        iterator
>        insert(const_iterator __position, const value_type& __x)
>        {
> @@ -299,6 +309,17 @@ namespace __debug
>        }
>  #endif
>
> +#ifdef __glibcxx_associative_heterogeneous_insertion
> +      template <__heterogeneous_tree_key<set> _Kt>
> +       iterator
> +       insert(const_iterator __position, _Kt&& __x)
> +       {
> +         __glibcxx_check_insert(__position);
> +         auto __it = _Base::insert(__position.base(), 
> std::forward<_Kt>(__x));
> +         return { __it, this };
> +       }
> +#endif
> +
>        template <typename _InputIterator>
>         void
>         insert(_InputIterator __first, _InputIterator __last)
> diff --git a/libstdc++-v3/include/debug/unordered_map 
> b/libstdc++-v3/include/debug/unordered_map
> index 4bde18c917b..1dda76dcf32 100644
> --- a/libstdc++-v3/include/debug/unordered_map
> +++ b/libstdc++-v3/include/debug/unordered_map
> @@ -500,6 +500,17 @@ namespace __debug
>           return { { __res.first, this }, __res.second };
>         }
>
> +# ifdef __glibcxx_associative_heterogeneous_insertion
> +      template <__heterogeneous_hash_key<unordered_map> _Kt, typename... 
> _Args>
> +       pair<iterator, bool>
> +       try_emplace(_Kt&& __k, _Args&&... __args)
> +       {
> +         auto __res = _Base::try_emplace(std::forward<_Kt>(__k),
> +           std::forward<_Args>(__args)...);
> +         return { { __res.first, this }, __res.second };
> +       }
> +# endif
> +
>        template <typename... _Args>
>         iterator
>         try_emplace(const_iterator __hint, const key_type& __k,
> @@ -516,10 +527,21 @@ namespace __debug
>         try_emplace(const_iterator __hint, key_type&& __k, _Args&&... __args)
>         {
>           __glibcxx_check_insert(__hint);
> -         return { _Base::try_emplace(__hint.base(), std::move(__k),
> -                                     std::forward<_Args>(__args)...),
> -                  this };
> +         auto __it = _Base::try_emplace(__hint.base(), std::move(__k),
> +           std::forward<_Args>(__args)...);
> +         return { __it, this };


Are all these try_emplace overloads missing calls to _M_check_rehashed?
I think I should have added those in r6-2989-g66c182be120bb3 when
adding try_emplace to the debug maps.
But  that's a pre-existing problem that can be solved separately.

This is OK for trunk (after the main P2363 patch is pushed, of course).






>         }
> +# ifdef __glibcxx_associative_heterogeneous_insertion
> +      template <__heterogeneous_hash_key<unordered_map> _Kt, typename... 
> _Args>
> +       iterator
> +       try_emplace(const_iterator __hint, _Kt&& __k, _Args&&... __args)
> +       {
> +         __glibcxx_check_insert(__hint);
> +         auto __it = _Base::try_emplace(__hint.base(),
> +           std::forward<_Kt>(__k), std::forward<_Args>(__args)...);
> +         return { __it, this };
> +       }
> +# endif
>
>        template <typename _Obj>
>         pair<iterator, bool>
> @@ -539,15 +561,26 @@ namespace __debug
>           return { { __res.first, this }, __res.second };
>         }
>
> +# ifdef __glibcxx_associative_heterogeneous_insertion
> +      template <__heterogeneous_hash_key<unordered_map> _Kt, typename _Obj>
> +       pair<iterator, bool>
> +       insert_or_assign(_Kt&& __k, _Obj&& __obj)
> +       {
> +         auto __res = _Base::insert_or_assign(
> +           std::forward<_Kt>(__k), std::forward<_Obj>(__obj));
> +         return { { __res.first, this }, __res.second };
> +       }
> +# endif
> +
>        template <typename _Obj>
>         iterator
>         insert_or_assign(const_iterator __hint, const key_type& __k,
>                          _Obj&& __obj)
>         {
>           __glibcxx_check_insert(__hint);
> -         return { _Base::insert_or_assign(__hint.base(), __k,
> -                                          std::forward<_Obj>(__obj)),
> -                  this };
> +         auto __it = _Base::insert_or_assign(__hint.base(), __k,
> +           std::forward<_Obj>(__obj));
> +         return { __it, this };
>         }
>
>        template <typename _Obj>
> @@ -555,10 +588,23 @@ namespace __debug
>         insert_or_assign(const_iterator __hint, key_type&& __k, _Obj&& __obj)
>         {
>           __glibcxx_check_insert(__hint);
> -         return { _Base::insert_or_assign(__hint.base(), std::move(__k),
> -                                          std::forward<_Obj>(__obj)),
> -                  this };
> +         auto __it = _Base::insert_or_assign(__hint.base(), std::move(__k),
> +           std::forward<_Obj>(__obj));
> +         return { __it, this };
>         }
> +
> +# ifdef __glibcxx_associative_heterogeneous_insertion
> +      template <__heterogeneous_hash_key<unordered_map> _Kt, typename _Obj>
> +       iterator
> +       insert_or_assign(const_iterator __hint, _Kt&& __k, _Obj&& __obj)
> +       {
> +         __glibcxx_check_insert(__hint);
> +         auto __it = _Base::insert_or_assign(__hint.base(),
> +           std::forward<_Kt>(__k), std::forward<_Obj>(__obj));
> +         return { __it, this };
> +       }
> +# endif
> +
>  #endif // C++17
>
>  #ifdef __glibcxx_node_extract // >= C++17 && HOSTED
> diff --git a/libstdc++-v3/include/debug/unordered_set 
> b/libstdc++-v3/include/debug/unordered_set
> index de999a76890..06430e7cf64 100644
> --- a/libstdc++-v3/include/debug/unordered_set
> +++ b/libstdc++-v3/include/debug/unordered_set
> @@ -413,6 +413,18 @@ namespace __debug
>         return { { __res.first, this }, __res.second };
>        }
>
> +# ifdef __glibcxx_associative_heterogeneous_insertion
> +      template <__heterogeneous_hash_key<unordered_set> _Kt>
> +       std::pair<iterator, bool>
> +       insert(_Kt&& __obj)
> +       {
> +         size_type __bucket_count = this->bucket_count();
> +         auto __res = _Base::insert(std::forward<_Kt>(__obj));
> +         _M_check_rehashed(__bucket_count);
> +         return { { __res.first, this }, __res.second };
> +       }
> +#endif
> +
>        iterator
>        insert(const_iterator __hint, value_type&& __obj)
>        {
> @@ -423,6 +435,20 @@ namespace __debug
>         return { __it, this };
>        }
>
> +# ifdef __glibcxx_associative_heterogeneous_insertion
> +      template <__heterogeneous_hash_key<unordered_set> _Kt>
> +       iterator
> +       insert(const_iterator __hint, _Kt&& __obj)
> +       {
> +         __glibcxx_check_insert(__hint);
> +         size_type __bucket_count = this->bucket_count();
> +         auto __it = _Base::insert(
> +           __hint.base(), std::forward<_Kt>(__obj));
> +         _M_check_rehashed(__bucket_count);
> +         return { __it, this };
> +       }
> +#endif
> +
>        void
>        insert(std::initializer_list<value_type> __l)
>        {
> --
> 2.52.0
>

Reply via email to