Remove some preprocessor conditionals by moving the _M_size member for the cxx11 ABI into a new base class, which is empty for the gcc4-compat ABI.
Move some unused members that are only retained for ABI compatibility to the end of _List_base and add an explanatory comment. Stop using list::_M_node_count and list::_D_distance and then move them to the end of std::list with a comment too. libstdc++-v3/ChangeLog: * include/bits/stl_list.h (_List_size): New struct. (_List_node_header): Replace _M_size member with _List_size base class. (_List_node_header(_List_node_header&&)): Replace explicit uses of _M_size with initializing the base. (_List_node_header::_M_init): Likewise. (_List_base::_S_distance, _List_base::_M_distance) (_List_base::_M_node_count): Move to end of class body and add comment. (list::_S_distance, list::_M_node_count): Likewise. (list::size): Inline _M_node_count effects to here. (list::splice(iterator, list&, iterator, iterator)): Use #if and call std::distance instead of _S_distance. --- Tested x86_64-linux. Pull request at https://forge.sourceware.org/gcc/gcc-TEST/pulls/25 libstdc++-v3/include/bits/stl_list.h | 179 +++++++++++++++------------ 1 file changed, 97 insertions(+), 82 deletions(-) diff --git a/libstdc++-v3/include/bits/stl_list.h b/libstdc++-v3/include/bits/stl_list.h index 7deb04b4bfe..d51fde90e2b 100644 --- a/libstdc++-v3/include/bits/stl_list.h +++ b/libstdc++-v3/include/bits/stl_list.h @@ -104,22 +104,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_unhook() _GLIBCXX_USE_NOEXCEPT; }; - /// The %list node header. - struct _List_node_header : public _List_node_base + struct _List_size { #if _GLIBCXX_USE_CXX11_ABI - std::size_t _M_size; + // Store the size here so that std::list::size() is fast. + size_t _M_size; #endif + }; + + /// The %list node header. + struct _List_node_header : public _List_node_base, _List_size + { _List_node_header() _GLIBCXX_NOEXCEPT { _M_init(); } #if __cplusplus >= 201103L _List_node_header(_List_node_header&& __x) noexcept - : _List_node_base{ __x._M_next, __x._M_prev } -# if _GLIBCXX_USE_CXX11_ABI - , _M_size(__x._M_size) -# endif + : _List_node_base(__x), _List_size(__x) { if (__x._M_base()->_M_next == __x._M_base()) this->_M_next = this->_M_prev = this; @@ -142,9 +144,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __node->_M_next = __xnode->_M_next; __node->_M_prev = __xnode->_M_prev; __node->_M_next->_M_prev = __node->_M_prev->_M_next = __node; -# if _GLIBCXX_USE_CXX11_ABI - _M_size = __x._M_size; -# endif + _List_size::operator=(__x); __x._M_init(); } } @@ -154,9 +154,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION _M_init() _GLIBCXX_NOEXCEPT { this->_M_next = this->_M_prev = this; -#if _GLIBCXX_USE_CXX11_ABI - this->_M_size = 0; -#endif + _List_size::operator=(_List_size()); } private: @@ -436,21 +434,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 rebind<_List_node<_Tp> >::other _Node_alloc_type; typedef __gnu_cxx::__alloc_traits<_Node_alloc_type> _Node_alloc_traits; -#if !_GLIBCXX_INLINE_VERSION - static size_t - _S_distance(const __detail::_List_node_base* __first, - const __detail::_List_node_base* __last) - { - size_t __n = 0; - while (__first != __last) - { - __first = __first->_M_next; - ++__n; - } - return __n; - } -#endif - struct _List_impl : public _Node_alloc_type { @@ -488,33 +471,12 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 void _M_inc_size(size_t __n) { _M_impl._M_node._M_size += __n; } void _M_dec_size(size_t __n) { _M_impl._M_node._M_size -= __n; } - -# if !_GLIBCXX_INLINE_VERSION - size_t - _M_distance(const __detail::_List_node_base* __first, - const __detail::_List_node_base* __last) const - { return _S_distance(__first, __last); } - - // return the stored size - size_t _M_node_count() const { return _M_get_size(); } -# endif #else // dummy implementations used when the size is not stored size_t _M_get_size() const { return 0; } void _M_set_size(size_t) { } void _M_inc_size(size_t) { } void _M_dec_size(size_t) { } - -# if !_GLIBCXX_INLINE_VERSION - size_t _M_distance(const void*, const void*) const { return 0; } - - // count the number of nodes - size_t _M_node_count() const - { - return _S_distance(_M_impl._M_node._M_next, - std::__addressof(_M_impl._M_node)); - } -# endif #endif typename _Node_alloc_traits::pointer @@ -549,16 +511,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 #if __cplusplus >= 201103L _List_base(_List_base&&) = default; -# if !_GLIBCXX_INLINE_VERSION - _List_base(_List_base&& __x, _Node_alloc_type&& __a) - : _M_impl(std::move(__a)) - { - if (__x._M_get_Node_allocator() == _M_get_Node_allocator()) - _M_move_nodes(std::move(__x)); - // else caller must move individual elements. - } -# endif - // Used when allocator is_always_equal. _List_base(_Node_alloc_type&& __a, _List_base&& __x) : _M_impl(std::move(__a), std::move(__x._M_impl)) @@ -584,6 +536,57 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 void _M_init() _GLIBCXX_NOEXCEPT { this->_M_impl._M_node._M_init(); } + +#if !_GLIBCXX_INLINE_VERSION + // XXX GLIBCXX_ABI Deprecated + // These members are unused by std::list now, but we keep them here + // so that an explicit instantiation of std::list will define them. + // This ensures that explicit instantiations still define these symbols, + // so that explicit instantiation declarations of std::list that were + // compiled with old versions of GCC can still find these old symbols. + +# if __cplusplus >= 201103L + _List_base(_List_base&& __x, _Node_alloc_type&& __a) + : _M_impl(std::move(__a)) + { + if (__x._M_get_Node_allocator() == _M_get_Node_allocator()) + _M_move_nodes(std::move(__x)); + // else caller must move individual elements. + } +# endif + + static size_t + _S_distance(const __detail::_List_node_base* __first, + const __detail::_List_node_base* __last) + { + size_t __n = 0; + while (__first != __last) + { + __first = __first->_M_next; + ++__n; + } + return __n; + } + +#if _GLIBCXX_USE_CXX11_ABI + size_t + _M_distance(const __detail::_List_node_base* __first, + const __detail::_List_node_base* __last) const + { return _S_distance(__first, __last); } + + // return the stored size + size_t _M_node_count() const { return _M_get_size(); } +#else + size_t _M_distance(const void*, const void*) const { return 0; } + + // count the number of nodes + size_t _M_node_count() const + { + return _S_distance(_M_impl._M_node._M_next, + std::__addressof(_M_impl._M_node)); + } +#endif +#endif // ! INLINE_VERSION }; /** @@ -721,27 +724,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 } #endif -#if _GLIBCXX_USE_CXX11_ABI - static size_t - _S_distance(const_iterator __first, const_iterator __last) - { return std::distance(__first, __last); } - - // return the stored size - size_t - _M_node_count() const - { return this->_M_get_size(); } -#else - // dummy implementations used when the size is not stored - static size_t - _S_distance(const_iterator, const_iterator) - { return 0; } - - // count the number of nodes - size_t - _M_node_count() const - { return std::distance(begin(), end()); } -#endif - public: // [23.2.2.1] construct/copy/destroy // (assign() and get_allocator() are also listed in this section) @@ -1193,7 +1175,13 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 _GLIBCXX_NODISCARD size_type size() const _GLIBCXX_NOEXCEPT - { return _M_node_count(); } + { +#if _GLIBCXX_USE_CXX11_ABI + return this->_M_get_size(); // return the stored size +#else + return std::distance(begin(), end()); // count the number of nodes +#endif + } /** Returns the size() of the largest possible %list. */ _GLIBCXX_NODISCARD @@ -1851,9 +1839,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 if (this != std::__addressof(__x)) _M_check_equal_allocators(__x); - size_t __n = _S_distance(__first, __last); +#if _GLIBCXX_USE_CXX11_ABI + size_t __n = std::distance(__first, __last); this->_M_inc_size(__n); __x._M_dec_size(__n); +#endif this->_M_transfer(__position._M_const_cast(), __first._M_const_cast(), @@ -2213,6 +2203,31 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11 { explicit _Finalize_merge(list&, list&, const iterator&) { } }; #endif +#if !_GLIBCXX_INLINE_VERSION + // XXX GLIBCXX_ABI Deprecated + // These members are unused by std::list now, but we keep them here + // so that an explicit instantiation of std::list will define them. + // This ensures that any objects or libraries compiled against old + // versions of GCC will still be able to use the symbols. + +#if _GLIBCXX_USE_CXX11_ABI + static size_t + _S_distance(const_iterator __first, const_iterator __last) + { return std::distance(__first, __last); } + + size_t + _M_node_count() const + { return this->_M_get_size(); } +#else + static size_t + _S_distance(const_iterator, const_iterator) + { return 0; } + + size_t + _M_node_count() const + { return std::distance(begin(), end()); } +#endif +#endif // ! INLINE_VERSION }; #if __cpp_deduction_guides >= 201606 -- 2.47.0