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:
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?
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 thekey_type
andmapped_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.