Default std::list default and move constructors

Jonathan Wakely
Tue Jul 18 13:28:00 GMT 2017

On 12/07/17 22:12 +0200, François Dumont wrote:
>On 05/07/2017 17:22, Jonathan Wakely wrote:
>>It's mostly good, but I'd like to make a few suggestions ...
>>>diff --git a/libstdc++-v3/include/bits/stl_list.h 
>>>index 232885a..7ffffe5 100644
>>>--- a/libstdc++-v3/include/bits/stl_list.h
>>>+++ b/libstdc++-v3/include/bits/stl_list.h
>>>@@ -82,6 +82,17 @@ namespace std _GLIBCXX_VISIBILITY(default)
>>>      _List_node_base* _M_next;
>>>      _List_node_base* _M_prev;
>>>+#if __cplusplus >= 201103L
>>>+      _List_node_base() = default;
>>>+      _List_node_base()
>>>+      { }
>>>+      _List_node_base(_List_node_base* __next, _List_node_base* __prev)
>>>+    : _M_next(__next), _M_prev(__prev)
>>>+      { }
>>I think I'd prefer to leave this struct with no user-defined
>>constructors, instead of adding these.
>My goal was to make sure that as much as possible instances are 
>initialized through their initialization list. But it is still 
>possible without it so I made the change.
>>>      static void
>>>      swap(_List_node_base& __x, _List_node_base& __y) 
>>>@@ -99,6 +110,79 @@ namespace std _GLIBCXX_VISIBILITY(default)
>>>      _M_unhook() _GLIBCXX_USE_NOEXCEPT;
>>>    };
>>>+    /// The %list node header.
>>>+    struct _List_node_header : public _List_node_base
>>>+    {
>>>+    private:
>>>+      std::size_t _M_size;
>>I don't think this needs to be private, because we don't have to worry
>>about users accessing this member. It's an internal-only type, and the
>>_M_next and _M_prev members are already public.
>It's not internal-only as those members are exposed on std::list 
>through inheritance. But I agree that consistency is more important 
>here so I made it public.

Looks like it's only used as a base class of _List_impl, which is
private to std::list, and in the __distance overload. Am I missing

>>If it's public then the _List_base::_M_inc_size, _M_dec_size etc.
>>could access it directly, and we don't need to add duplicates of those
>>functions to _List_impl.
>>>+      _List_node_base* _M_base() { return this; }
>>Is this function necessary?
>It is a nice replacement for calls to __addressof.

OK, that does make it more readable.

>>>-      size_t _M_get_size() const { return 
>>>*_M_impl._M_node._M_valptr(); }
>>>+      size_t
>>>+      _M_get_size() const { return _M_impl._M_node._M_get_size(); }
>>>-      void _M_set_size(size_t __n) { *_M_impl._M_node._M_valptr() 
>>>= __n; }
>>>+      void
>>>+      _M_set_size(size_t __n) { _M_impl._M_node._M_set_size(__n); }
>>>-      void _M_inc_size(size_t __n) { *_M_impl._M_node._M_valptr() 
>>>+= __n; }
>>>+      void
>>>+      _M_inc_size(size_t __n) { _M_impl._M_node._M_inc_size(__n); }
>>>-      void _M_dec_size(size_t __n) { *_M_impl._M_node._M_valptr() 
>>>-= __n; }
>>>+      void
>>>+      _M_dec_size(size_t __n) { _M_impl._M_node._M_dec_size(__n); }
>>These functions could just access _M_impl._M_size directly if it was
>>public. Introducing new functions to _List_impl to be used here seems
>>like unnecessary complication. We don't get rid of the #if because
>>it's still needed for these functions anyway:
>Yes, I wanted to manage as much as possible usage of C++11 abi in the 
>new _List_node_header type.

N.B. the ABI is called "cxx11" not C++11. It's a bad name, I should
have called it something else, but please don't make it worse by
saying "C++11". That ABI is also the default for C++98 so saying
"C++11" just causes more confusion than necessary.

You're not getting rid of the #if entirely, so some of the cxx11 ABI
specialization already lives in _List_base. Adding several new member
functions and still failing to remove the #if#else from _List_base
didn't seem like an improvement. The new patch looks much better to

>So here is the new patch limited to this evolution. Optimization for 
>always equal allocator will come after along with another 
>simplification to replace _S_distance with std::distance.


>Tests running, ok to commit if successful ?

OK for trunk with one tiny tweak, while you're already changing the
function ...

>@@ -1983,12 +2011,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
> 	       _GLIBCXX_STD_C::_List_const_iterator<_Tp> __last,
> 	       input_iterator_tag)
>     {
>-      typedef _GLIBCXX_STD_C::_List_node<size_t> _Sentinel;
>+      typedef __detail::_List_node_header _Sentinel;
>       _GLIBCXX_STD_C::_List_const_iterator<_Tp> __beyond = __last;
>       ++__beyond;
>       bool __whole = __first == __beyond;

Could you please make __whole const?


More information about the Libstdc++ mailing list