g++4.9.2 and rvalue reference maps

87 views Asked by At

So, I have the following code:

#include <map>
#include <string>
#include <iostream>

struct MockMapItem {
    std::string property;

    MockMapItem(const std::string& value) : property(value) {
        std::cout << "constructed MockMapItem with a string!" << std::endl;

    }
};

typedef typename std::map<std::string, const MockMapItem&& > ItemMap;

int main()
{
    MockMapItem map_item("some string value");

    ItemMap themap;
    themap.emplace("something", std::move(map_item));

}

For ease of access, I have put it here:

http://coliru.stacked-crooked.com/a/7e80bc37d904510d

and here:

http://ideone.com/2wkOmC

Now comes the fun:

the coliru site compiles and runs it.

The ideone one gives the following error:

Compilation error   time: 0 memory: 0 signal:0

prog.cpp:14:60: error: template argument 2 is invalid
 typedef typename std::map<std::string, const MockMapItem&& > ItemMap;
                                                        ^
prog.cpp:14:60: error: template argument 4 is invalid
prog.cpp:14:62: error: 'ItemMap' in namespace 'std' does not name a type
 typedef typename std::map<std::string, const MockMapItem&& > ItemMap;

But I can compile the code, although using g++4.8.4 (and clang 3.4)...

And now I'm wondering which one is right, and more specifically why?

1

There are 1 answers

0
Jonathan Wakely On

23.2.1 says that a container's value_type must be Erasable from the container, and 23.2.4 says that for maps and multimaps those requirements apply to the key_type and mapped_type.

A reference type is not Erasable from a container, because you cannot form a pointer to a reference type and cannot destroy it using allocator_traits::destroy (because allocators only support non-const object types, and a reference type is not an object type).

So the const MockMapItem&& type fails to meet the requirements for use in containers, and so has undefined behaviour.

Edit: actually in C++11 the requirement in 23.2.1 was just that value_type is Destructible, and a reference type is destructible. So maybe this is well-formed in C++11, but not C++14. Hmm.