R-value inserts don't work for unordered_map
Asked Answered
U

2

7

I'm using the latest available GCC build from repository. I decided to use it because some additional C++0x features. However now I stuck with something what supposes to work - I want to add new element to map via r-value. Simplified code, which demonstrates problem:

#include <tr1/unordered_map>

class X
{
    public:
        X (void) { /* ... */ };
        X (const X& x) = delete;
        X (X&& x) { /* ... */ };
};

int main (void)
{
    std::tr1::unordered_map<int, X> map;

    // using std::tr1::unordered_map<int, X>::value_type didn't help too
    std::pair<int, X> value (1, X ());

    map.insert (std::move (value));
}

Notice, that when replace X class with some primitive type like int code compiles and work just fine.

In my production code class corresponding to X doesn't have copy constructor too.

Error message is (like all template-related errors) long and unreadable and I'm not sure if it's good idea to put it here. Notify me if you want error message, so I'll update this question. Last part of message is interesting:

(...)
/usr/include/c++/trunk/ext/new_allocator.h:106:9: error: use of deleted function ‘constexpr std::pair<_T1, _T2>::pair(const std::pair<_T1, _T2>&) [with _T1 = const int, _T2 = X, std::pair<_T1, _T2> = std::pair<const int, X>]’
In file included from /usr/include/c++/trunk/utility:71:0,
                 from /usr/include/c++/trunk/tr1/unordered_map:34,
                 from kod.cpp:1:
/usr/include/c++/trunk/bits/stl_pair.h:110:17: error: ‘constexpr std::pair<_T1, _T2>::pair(const std::pair<_T1, _T2>&) [with _T1 = const int, _T2 = X, std::pair<_T1, _T2> = std::pair<const int, X>]’ is implicitly deleted because the default definition would be ill-formed:
/usr/include/c++/trunk/bits/stl_pair.h:110:17: error: use of deleted function ‘X::X(const X&)’

Moreover this should work, because similar bug was already fixed [C++0x] Implement emplace* in associative and unordered containers.

Maybe I'm doing something wrong? I want to be sure, that's GCC or libstdc++ bug before reporting it.

Unexperienced answered 26/1, 2011 at 20:49 Comment(1)
Missing R-Value compatible 'insert' method is now available in unreleased GCC 4.6.0.Unexperienced
P
5

Your code looks correct to me except for your use of tr1. tr1-qualified stuff doesn't know about rvalue reference or move semantics.

I took your code, removed tr1 from the header and namespace qualifiers, and successfully compiled your code using g++-4.4 and libc++ (http://libcxx.llvm.org/). Try removing tr1.

Pico answered 26/1, 2011 at 21:9 Comment(2)
Works,, weird some time ago compiler forced me to use "tr1" namespace when I was trying to use some of TR1 features...Unexperienced
tr1 refers to a non-normative technical report. That means that any features in it are considered optional - the standard doesn't require them. tr1 contained many of the library components which have subsequently been moved to C++0x. Sometimes during that move from std::tr1 to std::, the components were modified. Adding move semantics to unordered_map is an example of such a modification. tr1 predates C++0x. You may have been using a version which had tr1, but did not have C++0x features.Pico
K
0

The value_type of that unordered_map is not std::pair<int, X>. It is std::pair<const int, X>. Maybe if you use that type for the value it will work better.

decltype(map)::value_type value(1, X());
map.insert(std::move(value));

Although I don't exactly see why your code shouldn't work as is.

Kuhlmann answered 26/1, 2011 at 21:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.