Relax std::move_if_noexcept for std::pair

Jonathan Wakely jwakely@redhat.com
Fri Dec 21 13:31:00 GMT 2018


On 20/12/18 22:53 +0100, François Dumont wrote:
>On 12/20/18 9:04 AM, Ville Voutilainen wrote:
>>On Thu, 20 Dec 2018 at 08:29, François Dumont <frs.dumont@gmail.com> wrote:
>>>Hi
>>>
>>>      I eventually find out what was the problem with the
>>>std::move_if_noexcept within associative containers.
>>>
>>>      The std::pair move default constructor might not move both first
>>>and second member. If any is not moveable it will just copy it. And then
>>..as it should..
>>
>>>the noexcept qualification of the copy constructor will participate in
>>>the noexcept qualification of the std::pair move constructor. So
>>>std::move_if_noexcept can eventually decide to not use move because a
>>>_copy_ constructor not noexcept qualified.
>>..and again, as it should.
>>
>>>      This is why I am partially specializing __move_if_noexcept_cond. As
>>>there doesn't seem to exist any Standard meta function to find out if
>>>move will take place I resort using std::is_const as in this case for
>>>sure the compiler won't call the move constructor.
>>That seems wrong; just because a type is or is not const has nothing
>>to do whether
>>it's nothrow_move_constructible.
>
>Indeed, I am not changing that.
>
>
>>
>>I don't understand what problem this is solving, and how it's not
>>introducing new problems.
>>
>The problem I am trying to solve is shown by the tests I have adapted. 
>Allow more move semantic in associative container where key are stored 
>as const.

I'm not convinced that's a desirable property, especially not if it
needs changes to move_if_noexcept.

>But if I make counter_type copy constructor noexcept then I also get 
>the move on the pair.second instance, great. I am just surprise to 
>have to make a copy constructor noexcept to have std::move_if_noexcept 
>work as I expect.

Because the move constructor of pair<const T, U> will copy the first
element not move it, because you can't move from a const object. If
the T(const T&) constructor is noexcept, and the U(U&&) constructor is
also noexcept, then the pair<const T, U> move constructor is noexcept.
The move constructor's exception specification depends on the
exception specifications of whichever constructors it invokes for its
members.

>I think I just need to understand why we need std::move_if_noexcept in 
>unordered containers or even rb_tree. Couldn't we just use std::move ? 

No. If moving can throw then we can't provide strong exception safety.

>I don't understand what we are trying to avoid with this noexcept 
>check.

Then maybe stop trying to change how it works :-)



More information about the Libstdc++ mailing list