[Bug libstdc++/86127] STL containers do not satisfy container.requirements.general clause 8

2018-07-04 Thread redi at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86127

Jonathan Wakely  changed:

   What|Removed |Added

   Target Milestone|9.0 |7.4

--- Comment #13 from Jonathan Wakely  ---
(In reply to Jonathan Wakely from comment #6)
> I've removed the converting copies from forward_list.

For 7.4 and 8.2 as well as trunk.

[Bug libstdc++/86127] STL containers do not satisfy container.requirements.general clause 8

2018-07-04 Thread redi at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86127

--- Comment #12 from Jonathan Wakely  ---
Author: redi
Date: Wed Jul  4 13:59:42 2018
New Revision: 262411

URL: https://gcc.gnu.org/viewcvs?rev=262411&root=gcc&view=rev
Log:
PR libstdc++/86127 avoid unnecessary allocator conversions

There is no need to use an allocator of the correct value_type when
calling allocator_traits::construct and allocator_traits::destroy. The
existing node allocator can be used, instead of constructing a new
allocator object every time.

There's also no benefit to using __gnu_cxx::__alloc_traits instead of
std::allocator_traits to get the pointer and const_pointer types.
std::forward_list is only available for C++11 and later, when
std::allocator_traits is available too.

Backport from mainline
2018-06-13  Jonathan Wakely  

PR libstdc++/86127
* include/bits/forward_list.h (_Fwd_list_base::_Tp_alloc_type): Remove
unused typedef.
(_Fwd_list_base::_M_create_node, _Fwd_list_base::_M_erase_after):
Use node allocator to create and destroy elements.
(forward_list::_Tp_alloc_type): Remove unused typedef.
(forward_list::_Alloc_traits): Use allocator_traits instead of
__gnu_cxx::__alloc_traits.
* include/bits/forward_list.tcc (_Fwd_list_base::_M_erase_after):
Use node allocator to create and destroy elements.

Modified:
branches/gcc-7-branch/libstdc++-v3/ChangeLog
branches/gcc-7-branch/libstdc++-v3/include/bits/forward_list.h
branches/gcc-7-branch/libstdc++-v3/include/bits/forward_list.tcc

[Bug libstdc++/86127] STL containers do not satisfy container.requirements.general clause 8

2018-07-04 Thread redi at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86127

--- Comment #11 from Jonathan Wakely  ---
Author: redi
Date: Wed Jul  4 11:46:43 2018
New Revision: 262393

URL: https://gcc.gnu.org/viewcvs?rev=262393&root=gcc&view=rev
Log:
PR libstdc++/86127 avoid unnecessary allocator conversions

There is no need to use an allocator of the correct value_type when
calling allocator_traits::construct and allocator_traits::destroy. The
existing node allocator can be used, instead of constructing a new
allocator object every time.

There's also no benefit to using __gnu_cxx::__alloc_traits instead of
std::allocator_traits to get the pointer and const_pointer types.
std::forward_list is only available for C++11 and later, when
std::allocator_traits is available too.

Backport from mainline
2018-06-13  Jonathan Wakely  

PR libstdc++/86127
* include/bits/forward_list.h (_Fwd_list_base::_Tp_alloc_type): Remove
unused typedef.
(_Fwd_list_base::_M_create_node, _Fwd_list_base::_M_erase_after):
Use node allocator to create and destroy elements.
(forward_list::_Tp_alloc_type): Remove unused typedef.
(forward_list::_Alloc_traits): Use allocator_traits instead of
__gnu_cxx::__alloc_traits.

Modified:
branches/gcc-8-branch/libstdc++-v3/ChangeLog
branches/gcc-8-branch/libstdc++-v3/include/bits/forward_list.h
branches/gcc-8-branch/libstdc++-v3/include/bits/forward_list.tcc

[Bug libstdc++/86127] STL containers do not satisfy container.requirements.general clause 8

2018-06-13 Thread redi at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86127

--- Comment #10 from Jonathan Wakely  ---
As I said in comment 6, I've already removed the copies that forward_list does
on destruction.

As I said in comment 3, there are no copies in the default constructor, they're
in the initializer-list constructors. The standard says the initializer-list
constructors look like:

  vector(initializer_list, const Allocator& = Allocator());

That default argument needs to get copied into the vector's allocator member
somehow.

It could be avoided by defining:

  vector(initializer_list);
  vector(initializer_list, const Allocator&);

But doing so just to avoid making copies of a cheap-to-copy object is not a
good justification, and would make it impossible to explicitly instantiate the
container with a non-default constructible allocator type.

Node-based containers such as forward_list and map neede to convert the
allocator from the value_type to the node type. That can either happen once on
construction, or every time elements are inserted or erased. Doing it on
construction is the obvious choice, and that's where you see the "template copy
constructor" lines for forward_list and map.

The standard allows those copies, and they should be cheap. There is no bug
here.

[Bug libstdc++/86127] STL containers do not satisfy container.requirements.general clause 8

2018-06-13 Thread fidget324 at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86127

--- Comment #9 from Scott Constable  ---
(In reply to Jonathan Wakely from comment #8)
> (In reply to Scott Constable from comment #7)
> > (In reply to Jonathan Wakely from comment #1)
> > > The allocator requirements say that move construction must be equivalent 
> > > to
> > > copy construction, and allocators should be cheap to copy anyway. I don't
> > > consider this a bug.
> > 
> > To be nitpicky, it looks like this equivalence requirement was introduced
> > recently in the C++20 draft. I'm compiling using C++14.
> 
> It's a defect report, so applies to previous standards.
> 
> https://wg21.link/lwg2593
> 
> Applying that change selectively would be madness.

Ah, I wasn't aware this was a defect correction. I should have figured that out
myself.
> 
> > I agree that allocators should be cheap to copy, but as a general principle
> > I think that all objects should be copied only when necessary. This is the
> > behavior I have observed in STL containers in libc++, as shown in my example
> > above. It just makes sense to me that when an STL container is moved, its
> > allocator should be moved, and no copying should be performed.
> 
> And that's exactly what libstdc++ does. Your test fails to distinguish
> between copies/moves performed during move construction and other operations.


I misstated my argument here. The STL container move invokes one move from the
allocator, and this is correct. What I don't understand is why the other
copies, e.g. from the container default constructor and destructor, are
necessary. Particularly when libc++ does not exhibit this behavior.

[Bug libstdc++/86127] STL containers do not satisfy container.requirements.general clause 8

2018-06-13 Thread redi at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86127

--- Comment #8 from Jonathan Wakely  ---
(In reply to Scott Constable from comment #7)
> (In reply to Jonathan Wakely from comment #1)
> > The allocator requirements say that move construction must be equivalent to
> > copy construction, and allocators should be cheap to copy anyway. I don't
> > consider this a bug.
> 
> To be nitpicky, it looks like this equivalence requirement was introduced
> recently in the C++20 draft. I'm compiling using C++14.

It's a defect report, so applies to previous standards.

https://wg21.link/lwg2593

Applying that change selectively would be madness.

> I agree that allocators should be cheap to copy, but as a general principle
> I think that all objects should be copied only when necessary. This is the
> behavior I have observed in STL containers in libc++, as shown in my example
> above. It just makes sense to me that when an STL container is moved, its
> allocator should be moved, and no copying should be performed.

And that's exactly what libstdc++ does. Your test fails to distinguish between
copies/moves performed during move construction and other operations.

[Bug libstdc++/86127] STL containers do not satisfy container.requirements.general clause 8

2018-06-13 Thread fidget324 at gmail dot com
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86127

--- Comment #7 from Scott Constable  ---
(In reply to Jonathan Wakely from comment #1)
> The allocator requirements say that move construction must be equivalent to
> copy construction, and allocators should be cheap to copy anyway. I don't
> consider this a bug.

To be nitpicky, it looks like this equivalence requirement was introduced
recently in the C++20 draft. I'm compiling using C++14.

I agree that allocators should be cheap to copy, but as a general principle I
think that all objects should be copied only when necessary. This is the
behavior I have observed in STL containers in libc++, as shown in my example
above. It just makes sense to me that when an STL container is moved, its
allocator should be moved, and no copying should be performed.

[Bug libstdc++/86127] STL containers do not satisfy container.requirements.general clause 8

2018-06-13 Thread redi at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86127

Jonathan Wakely  changed:

   What|Removed |Added

 Status|REOPENED|RESOLVED
 Resolution|--- |FIXED
   Target Milestone|--- |9.0
   Severity|normal  |enhancement

--- Comment #6 from Jonathan Wakely  ---
I've removed the converting copies from forward_list.

[Bug libstdc++/86127] STL containers do not satisfy container.requirements.general clause 8

2018-06-13 Thread redi at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86127

--- Comment #5 from Jonathan Wakely  ---
Author: redi
Date: Wed Jun 13 15:14:48 2018
New Revision: 261554

URL: https://gcc.gnu.org/viewcvs?rev=261554&root=gcc&view=rev
Log:
PR libstdc++/86127 avoid unnecessary allocator conversions

There is no need to use an allocator of the correct value_type when
calling allocator_traits::construct and allocator_traits::destroy. The
existing node allocator can be used, instead of constructing a new
allocator object every time.

There's also no benefit to using __gnu_cxx::__alloc_traits instead of
std::allocator_traits to get the pointer and const_pointer types.
std::forward_list is only available for C++11 and later, when
std::allocator_traits is available too.

PR libstdc++/86127
* include/bits/forward_list.h (_Fwd_list_base::_Tp_alloc_type): Remove
unused typedef.
(_Fwd_list_base::_Node_alloc_traits): Use allocator_traits instead of
__gnu_cxx::__alloc_traits.
(_Fwd_list_base::_M_create_node, _Fwd_list_base::_M_erase_after):
Use node allocator to create and destroy elements.
(forward_list::_Tp_alloc_type): Remove unused typedef.
(forward_list::_Alloc_traits): Use allocator_traits instead of
__gnu_cxx::__alloc_traits.

Modified:
trunk/libstdc++-v3/ChangeLog
trunk/libstdc++-v3/include/bits/forward_list.h
trunk/libstdc++-v3/include/bits/forward_list.tcc

[Bug libstdc++/86127] STL containers do not satisfy container.requirements.general clause 8

2018-06-13 Thread redi at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86127

Jonathan Wakely  changed:

   What|Removed |Added

 Status|RESOLVED|REOPENED
   Last reconfirmed||2018-06-13
 Resolution|INVALID |---
 Ever confirmed|0   |1

--- Comment #4 from Jonathan Wakely  ---
We can avoid the "template copy constructor" lines with a trivial fix to
forward_list though, and then we get:

forward_list test
==
template copy constructor
move constructor
move constructor

map test
==
copy constructor
template copy constructor
move constructor
move constructor

vector test
==
copy constructor
move constructor

All copies come from the initializer-list constructors.

[Bug libstdc++/86127] STL containers do not satisfy container.requirements.general clause 8

2018-06-13 Thread redi at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86127

--- Comment #3 from Jonathan Wakely  ---
(In reply to Jonathan Wakely from comment #2)
> Also your test is flawed.
> 
> (In reply to Scott Constable from comment #0)
> > forward_list test
> > ==
> 
> These all come from the default constructor:

Oops, I meant from the initializer-list constructor, not the default
constructor.

[Bug libstdc++/86127] STL containers do not satisfy container.requirements.general clause 8

2018-06-13 Thread redi at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86127

Jonathan Wakely  changed:

   What|Removed |Added

 Status|UNCONFIRMED |RESOLVED
 Resolution|--- |INVALID

--- Comment #2 from Jonathan Wakely  ---
Also your test is flawed.

(In reply to Scott Constable from comment #0)
> forward_list test
> ==

These all come from the default constructor:

> template copy constructor
> move constructor
> template copy constructor
> template copy constructor
> template copy constructor
> template copy constructor

Only this comes from the move constructor:

> move constructor



> map test
> ==

These all come from the default constructor:

> copy constructor
> template copy constructor
> move constructor

Only this comes from the move constructor:

> move constructor
> 
> vector test
> ==

Only this comes from the move constructor:

> move constructor

These all come from the destructors:

> template copy constructor
> template copy constructor
> template copy constructor
> template copy constructor

So the move constructors all perform exactly one move construction, as
required.

[Bug libstdc++/86127] STL containers do not satisfy container.requirements.general clause 8

2018-06-13 Thread redi at gcc dot gnu.org
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86127

--- Comment #1 from Jonathan Wakely  ---
The allocator requirements say that move construction must be equivalent to
copy construction, and allocators should be cheap to copy anyway. I don't
consider this a bug.