[PATCH][_GLIBCXX_DEBUG] Hide _Safe_unordered_container methods
Jonathan Wakely
jwakely@redhat.com
Thu Mar 5 09:25:38 GMT 2026
On Thu, 05 Mar 2026 at 07:02 +0100, François Dumont wrote:
>libstdc++: [_GLIBCXX_DEBUG] Hide _Safe_unordered_container methods
>
>In _Safe_unordered_container the _M_invalidate_all and _M_invalidate_all_if
>are made public to be used in nested struct _UContMergeGuard.
>
>Thanks to friend declaration we can avoid those method to be accessible from
>user code.
>
>libstdc++-v3/ChangeLog:
>
> * include/debug/safe_unordered_container.h
> (_Safe_unordered_container::_UContInvalidatePred): Move
>outside class, at
> namespace scope. Declare friend.
> (_Safe_unordered_container::_UMContInvalidatePred): Likewise.
> (_Safe_unordered_container::_UContMergeGuard): Likewise.
> (_Safe_unordered_container::_M_invalidate_all): Make protected.
> (_Safe_unordered_container::_M_invalidate_all_if): Likewise.
>
>
>Tested under Linux x86_64.
>
>Ok to commit ?
>
>François
>
>diff --git a/libstdc++-v3/include/debug/safe_unordered_container.h b/libstdc++-v3/include/debug/safe_unordered_container.h
>index 3f8346acb3b..66aa29eb84b 100644
>--- a/libstdc++-v3/include/debug/safe_unordered_container.h
>+++ b/libstdc++-v3/include/debug/safe_unordered_container.h
>@@ -36,6 +36,77 @@
>
> namespace __gnu_debug
> {
>+ template<typename _Container>
>+ class _Safe_unordered_container;
>+
>+#if __cplusplus > 201402L
Please change this condition to:
#ifdef __glibcxx_node_extract // >= C++17 && HOSTED
since that's the C++17 feature that these helpers are for.
>+ template<typename _ExtractKey, typename _Source>
>+ struct _UContInvalidatePred
>+ {
>+ template<typename _Iterator>
>+ bool
>+ operator()(_Iterator __it) const
>+ { return _M_source._M_cont().count(_ExtractKey{}(*__it)) == 0; }
>+
>+ const _Safe_unordered_container<_Source>& _M_source;
>+ };
>+
>+ template<typename _ExtractKey, typename _Source>
>+ struct _UMContInvalidatePred
>+ {
>+ template<typename _Iterator>
>+ bool
>+ operator()(_Iterator __it) const
>+ {
>+ auto __rng =
>+ _M_source._M_cont()._M_base().equal_range(_ExtractKey{}(*__it));
>+ for (auto __rit = __rng.first;
>+ __rit != __rng.second; ++__rit)
>+ {
>+ if (__it == __rit)
>+ return false;
>+ }
>+
>+ return true;
>+ }
>+
>+ const _Safe_unordered_container<_Source>& _M_source;
>+ };
>+
>+ template<typename _Source, typename _InvalidatePred>
>+ struct _UContMergeGuard
>+ {
>+ _UContMergeGuard(_Safe_unordered_container<_Source>& __src) noexcept
>+ : _M_source(__src), _M_size(__src._M_cont().size()), _M_pred { __src }
>+ { }
>+
>+ _UContMergeGuard(const _UContMergeGuard&) = delete;
>+
>+ ~_UContMergeGuard()
>+ {
>+ const std::size_t __size = _M_source._M_cont().size();
>+ if (__size == _M_size)
>+ return;
>+
>+ __try
>+ {
>+ if (__size == 0)
>+ _M_source._M_invalidate_all();
>+ else
>+ _M_source._M_invalidate_all_if(_M_pred);
>+ }
>+ __catch(...)
>+ {
>+ _M_source._M_invalidate_all();
>+ }
>+ }
>+
>+ _Safe_unordered_container<_Source>& _M_source;
>+ const std::size_t _M_size;
>+ _InvalidatePred _M_pred;
>+ };
>+#endif // C++17
>+
> /**
> * @brief Base class for constructing a @a safe unordered container type
> * that tracks iterators that reference it.
>@@ -57,86 +128,29 @@ namespace __gnu_debug
> template<typename _Container>
> class _Safe_unordered_container : public _Safe_unordered_container_base
> {
>- _Container&
>- _M_cont() noexcept
>- { return *static_cast<_Container*>(this); }
>+ const _Container&
>+ _M_cont() const noexcept
>+ { return *static_cast<const _Container*>(this); }
>
> const _Safe_unordered_container*
> _M_self() const
> { return this; }
>
>-#if __cplusplus > 201402L
> protected:
>+#if __cplusplus > 201402L
Same change here.
OK for trunk with those changes, thanks.
> template<typename _ExtractKey, typename _Source>
>- struct _UContInvalidatePred
>- {
>- template<typename _Iterator>
>- bool
>- operator()(_Iterator __it) const
>- { return _M_source.count(_ExtractKey{}(*__it)) == 0; }
>-
>- const _Source& _M_source;
>- };
>+ friend struct ::__gnu_debug::_UContInvalidatePred;
>
> template<typename _ExtractKey, typename _Source>
>- struct _UMContInvalidatePred
>- {
>- template<typename _Iterator>
>- bool
>- operator()(_Iterator __it) const
>- {
>- auto __rng =
>- _M_source._M_base().equal_range(_ExtractKey{}(*__it));
>- for (auto __rit = __rng.first;
>- __rit != __rng.second; ++__rit)
>- {
>- if (__it == __rit)
>- return false;
>- }
>-
>- return true;
>- }
>-
>- const _Source& _M_source;
>- };
>+ friend struct ::__gnu_debug::_UMContInvalidatePred;
>
> template<typename _Source, typename _InvalidatePred>
>- struct _UContMergeGuard
>- {
>- _UContMergeGuard(_Source& __src) noexcept
>- : _M_source(__src), _M_size(__src.size()), _M_pred { __src }
>- { }
>-
>- _UContMergeGuard(const _UContMergeGuard&) = delete;
>-
>- ~_UContMergeGuard()
>- {
>- const std::size_t __size = _M_source.size();
>- if (__size == _M_size)
>- return;
>-
>- __try
>- {
>- if (__size == 0)
>- _M_source._M_invalidate_all();
>- else
>- _M_source._M_invalidate_all_if(_M_pred);
>- }
>- __catch(...)
>- {
>- _M_source._M_invalidate_all();
>- }
>- }
>-
>- _Source& _M_source;
>- const std::size_t _M_size;
>- _InvalidatePred _M_pred;
>- };
>+ friend struct ::__gnu_debug::_UContMergeGuard;
>
> template<typename _ExtractKey, typename _Source>
> static _UContMergeGuard<_Source,
> _UContInvalidatePred<_ExtractKey, _Source>>
>- _S_uc_guard(_ExtractKey, _Source& __src)
>+ _S_uc_guard(_ExtractKey, _Safe_unordered_container<_Source>& __src)
> {
> typedef _UContInvalidatePred<_ExtractKey, _Source> _InvalidatePred;
> return _UContMergeGuard<_Source, _InvalidatePred>(__src);
>@@ -145,14 +159,13 @@ namespace __gnu_debug
> template<typename _ExtractKey, typename _Source>
> static _UContMergeGuard<_Source,
> _UMContInvalidatePred<_ExtractKey, _Source>>
>- _S_umc_guard(_ExtractKey, _Source& __src)
>+ _S_umc_guard(_ExtractKey, _Safe_unordered_container<_Source>& __src)
> {
> typedef _UMContInvalidatePred<_ExtractKey, _Source> _InvalidatePred;
> return _UContMergeGuard<_Source, _InvalidatePred>(__src);
> }
> #endif // C++17
>
>- public:
> void
> _M_invalidate_all()
> {
>@@ -179,7 +192,6 @@ namespace __gnu_debug
> _M_invalidate_local_if(__pred, sentry);
> }
>
>- protected:
> template<typename _VictimIt>
> void
> _M_invalidate(_VictimIt __victim)
More information about the Libstdc++
mailing list