该错误是因为在代码中的某个地方,map想要复制一个std::pair<int, std::unique_ptr<Entity>>
,但是没有能够执行此操作的复制构造函数,因为 unique_ptr 不可复制构造。这是特别不可能防止多个指针拥有相同的内存。
所以在 std::move 之前,没有办法使用不可复制的元素。
有一些解决方案here https://stackoverflow.com/questions/6231336/is-is-possible-to-use-stdmap-in-c-with-a-class-without-any-copy-operator.
但是,在 c++11 中,Map 可以利用 std::move 来处理不可复制的值。
这是通过提供另一个插入运算符来完成的,该运算符被重载以包含以下签名:
template< class P > std::pair<iterator,bool> insert( P&& value );
这意味着可以转换为 value_type 的类的右值可以用作参数。旧的插入仍然可用:
std::pair<iterator,bool> insert( const value_type& value );
此插入实际上复制了 value_type,这会导致错误,因为 value_type 不可复制构造。
我认为编译器正在选择非模板化重载,这会导致编译错误。因为它不是模板,所以它的失败就是一个错误。至少在 gcc 上,使用 std::move 的另一个插入是有效的。
以下是测试代码,用于查看您的编译器是否正确支持此功能:
#include <iostream>
#include <memory>
#include <utility>
#include <type_traits>
class Foo {
};
using namespace std;
int main() {
cout << is_constructible<pair<const int,unique_ptr<Foo> >, pair<const int,unique_ptr<Foo> >& >::value << '\n';
cout << is_constructible<pair<const int,unique_ptr<Foo> >, pair<const int,unique_ptr<Foo> >&& >::value << '\n';
}
第一行将输出0,因为复制构造无效。由于移动构造,第二行将输出 1is valid.
这段代码:
map.insert(std::move(EntityMap::value_type(entity->getId(), std::move(entity))));
应该调用移动插入过载。
这段代码:
map.insert<EntityMap::value_type>(EntityMap::value_type(entity->getId(), std::move(entity))));
确实应该这么称呼。
编辑:谜团仍在继续, vc 返回错误的 11 进行测试......