Bug 57619 - [4.8/4.9 Regression] std::unordered_map and std::unordered_multimap::insert invoking std::pair move constructor
[4.8/4.9 Regression] std::unordered_map and std::unordered_multimap::insert i...
Status: RESOLVED FIXED
Product: gcc
Classification: Unclassified
Component: libstdc++
4.8.1
: P3 normal
: 4.8.2
Assigned To: Paolo Carlini
:
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2013-06-14 21:41 UTC by Jesse Good
Modified: 2013-06-15 11:48 UTC (History)
0 users

See Also:
Host:
Target:
Build:
Known to work:
Known to fail: 4.8.1
Last reconfirmed: 2013-06-14 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Jesse Good 2013-06-14 21:41:14 UTC
The following code is invoking the std::pair move constructor:

int main ()
{
    std::unordered_map<std::string, std::string> mymap;
    std::unordered_multimap<std::string, std::string> mymultimap;
    std::pair<std::string, std::string> mypair{std::string("key"), std::string("value")};
    mymultimap.insert(mypair); // std::pair move constructor invoked here
    mymap.insert(mypair); // strings already moved out!
}

This seems related to http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53657.

As far as I can tell, overload resolution is choosing `insert(_Pair&& __x)` over `insert(const value_type& __x)`. Since this is an lvalue, the latter should be chosen. This happens for std::unordered_map::insert and std::unordered_multimap::insert.
Comment 1 Jonathan Wakely 2013-06-14 22:07:47 UTC
(In reply to Jesse Good from comment #0)
> The following code is invoking the std::pair move constructor:

Complete testcase:

#include <unordered_map>
#include <string>
#include <cassert>
int main ()
{
    std::unordered_multimap<std::string, std::string> mymultimap;
    std::pair<std::string, std::string> mypair{std::string("key"), std::string("value")};
    mymultimap.insert(mypair); // std::pair move constructor invoked here
    assert( mypair.first.length() && mypair.second.length() );
}

> As far as I can tell, overload resolution is choosing `insert(_Pair&& __x)`
> over `insert(const value_type& __x)`. Since this is an lvalue, the latter
> should be chosen.

Calling that overload is correct, the problem is that it uses std::move() not std::forward<_Pair>
Comment 2 Paolo Carlini 2013-06-14 23:03:38 UTC
Let's fix this.
Comment 3 Paolo Carlini 2013-06-14 23:39:37 UTC
Fixed mainline and 4.8.2.
Comment 4 Jonathan Wakely 2013-06-15 11:48:51 UTC
That was quick, thanks, Paolo!