https://gcc.gnu.org/g:dae387d2c81eace093f3c9a2e6e3f027a615e23f
commit r16-7918-gdae387d2c81eace093f3c9a2e6e3f027a615e23f Author: François Dumont <[email protected]> Date: Thu Mar 5 06:40:23 2026 +0100 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. Reviewed-by: Jonathan Wakely <[email protected]> Diff: --- .../include/debug/safe_unordered_container.h | 150 +++++++++++---------- 1 file changed, 81 insertions(+), 69 deletions(-) diff --git a/libstdc++-v3/include/debug/safe_unordered_container.h b/libstdc++-v3/include/debug/safe_unordered_container.h index 3f8346acb3bd..ec4af0986b5d 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; + +#ifdef __glibcxx_node_extract // >= C++17 && HOSTED + 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 && HOSTED + /** * @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: +#ifdef __glibcxx_node_extract // >= C++17 && HOSTED 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 +#endif // >= C++17 && HOSTED - 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)
