无法创建 MoveConstructibles 地图
我有一个包含 std::unique_ptr<> 的类,并且我想将此类的实例放入 std::map<>
中。我认为推动 C++ 引入移动语义的原因之一是可以将 unique_ptrs
之类的东西放入标准容器中(对于向量而言,这确实有效)。但在我看来, std::map
不喜欢这个想法。为什么会这样呢?
#include <map>
#include <memory>
int main()
{
std::map<int,std::unique_ptr<int>> map;
// error on the line that follows (use of disabled lvalue copy constructor)
map.insert(std::make_pair(1,std::unique_ptr<int>(new int(2))));
return 0;
}
谢谢。
-- 编辑
为了更清楚,确切的错误消息是:
mingw32-g++.exe --std=gnu++0x -ID:\CodeEnv\Libraries\Boost -c D:\CodeEnv\CodeMess\Untitled1.cpp -o D:\CodeEnv\CodeMess\Untitled1.o
mingw32-g++.exe -o D:\CodeEnv\CodeMess\Untitled1.exe D:\CodeEnv\CodeMess\Untitled1.o
In file included from c:\mingw\bin\../lib/gcc/mingw32/4.4.1/include/c++/bits/stl_algobase.h:66,
from c:\mingw\bin\../lib/gcc/mingw32/4.4.1/include/c++/bits/stl_tree.h:62,
from c:\mingw\bin\../lib/gcc/mingw32/4.4.1/include/c++/map:60,
from D:\CodeEnv\CodeMess\Untitled1.cpp:1:
c:\mingw\bin\../lib/gcc/mingw32/4.4.1/include/c++/bits/unique_ptr.h: In copy constructor 'std::pair<const int, std::unique_ptr<int, std::default_delete<int> > >::pair(const std::pair<const int, std::unique_ptr<int, std::default_delete<int> > >&)':
c:\mingw\bin\../lib/gcc/mingw32/4.4.1/include/c++/bits/stl_pair.h:68: instantiated from 'std::_Rb_tree_node<_Val>::_Rb_tree_node(_Args&& ...) [with _Args = const std::pair<const int, std::unique_ptr<int, std::default_delete<int> > >&, _Val = std::pair<const int, std::unique_ptr<int, std::default_delete<int> > >]'
c:\mingw\bin\../lib/gcc/mingw32/4.4.1/include/c++/ext/new_allocator.h:111: instantiated from 'void __gnu_cxx::new_allocator<_Tp>::construct(_Tp*, _Args&& ...) [with _Args = const std::pair<const int, std::unique_ptr<int, std::default_delete<int> > >&, _Tp = std::_Rb_tree_node<std::pair<const int, std::unique_ptr<int, std::default_delete<int> > > >]'
c:\mingw\bin\../lib/gcc/mingw32/4.4.1/include/c++/bits/stl_tree.h:394: instantiated from 'std::_Rb_tree_node<_Val>* std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_create_node(_Args&& ...) [with _Args = const std::pair<const int, std::unique_ptr<int, std::default_delete<int> > >&, _Key = int, _Val = std::pair<const int, std::unique_ptr<int, std::default_delete<int> > >, _KeyOfValue = std::_Select1st<std::pair<const int, std::unique_ptr<int, std::default_delete<int> > > >, _Compare = std::less<int>, _Alloc = std::allocator<std::pair<const int, std::unique_ptr<int, std::default_delete<int> > > >]'
c:\mingw\bin\../lib/gcc/mingw32/4.4.1/include/c++/bits/stl_tree.h:881: instantiated from 'std::_Rb_tree_iterator<_Val> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_insert_(const std::_Rb_tree_node_base*, const std::_Rb_tree_node_base*, const _Val&) [with _Key = int, _Val = std::pair<const int, std::unique_ptr<int, std::default_delete<int> > >, _KeyOfValue = std::_Select1st<std::pair<const int, std::unique_ptr<int, std::default_delete<int> > > >, _Compare = std::less<int>, _Alloc = std::allocator<std::pair<const int, std::unique_ptr<int, std::default_delete<int> > > >]'
c:\mingw\bin\../lib/gcc/mingw32/4.4.1/include/c++/bits/stl_tree.h:1177: instantiated from 'std::pair<typename std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator, bool> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_insert_unique(const _Val&) [with _Key = int, _Val = std::pair<const int, std::unique_ptr<int, std::default_delete<int> > >, _KeyOfValue = std::_Select1st<std::pair<const int, std::unique_ptr<int, std::default_delete<int> > > >, _Compare = std::less<int>, _Alloc = std::allocator<std::pair<const int, std::unique_ptr<int, std::default_delete<int> > > >]'
c:\mingw\bin\../lib/gcc/mingw32/4.4.1/include/c++/bits/stl_map.h:500: instantiated from 'std::pair<typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename _Alloc::rebind<std::pair<const _Key, _Tp> >::other>::iterator, bool> std::map<_Key, _Tp, _Compare, _Alloc>::insert(const std::pair<const _Key, _Tp>&) [with _Key = int, _Tp = std::unique_ptr<int, std::default_delete<int> >, _Compare = std::less<int>, _Alloc = std::allocator<std::pair<const int, std::unique_ptr<int, std::default_delete<int> > > >]'
D:\CodeEnv\CodeMess\Untitled1.cpp:7: instantiated from here
c:\mingw\bin\../lib/gcc/mingw32/4.4.1/include/c++/bits/unique_ptr.h:214: error: deleted function 'std::unique_ptr<_Tp, _Tp_Deleter>::unique_ptr(const std::unique_ptr<_Tp, _Tp_Deleter>&) [with _Tp = int, _Tp_Deleter = std::default_delete<int>]'
c:\mingw\bin\../lib/gcc/mingw32/4.4.1/include/c++/bits/stl_pair.h:68: error: used here
In file included from c:\mingw\bin\../lib/gcc/mingw32/4.4.1/include/c++/map:60,
from D:\CodeEnv\CodeMess\Untitled1.cpp:1:
c:\mingw\bin\../lib/gcc/mingw32/4.4.1/include/c++/bits/stl_tree.h: In constructor 'std::_Rb_tree_node<_Val>::_Rb_tree_node(_Args&& ...) [with _Args = const std::pair<const int, std::unique_ptr<int, std::default_delete<int> > >&, _Val = std::pair<const int, std::unique_ptr<int, std::default_delete<int> > >]':
c:\mingw\bin\../lib/gcc/mingw32/4.4.1/include/c++/bits/stl_tree.h:136: note: synthesized method 'std::pair<const int, std::unique_ptr<int, std::default_delete<int> > >::pair(const std::pair<const int, std::unique_ptr<int, std::default_delete<int> > >&)' first required here
看起来这是 std::pair<>
的问题,但单独使用时效果非常好:
int main()
{
std::pair<int,std::unique_ptr<int>> pair;
pair = std::make_pair(1,std::unique_ptr<int>(new int(2))); // no errors
return 0;
}
虽然这显然是并不意味着它不能被滥用:
int main()
{
std::pair<int,std::unique_ptr<int>> pair1,pair2;
pair1 = std::make_pair(1,std::unique_ptr<int>(new int(2))); // no errors
pair2 = pair1; // BOOM ! Copy from lvalue
return 0;
}
这可能是 std::map
内部发生的情况。
线索?
-- 编辑
查看错误消息,这确实是 TDM-GCC 4.4.1 的 std::map
实现的问题。它似乎没有像 std::vector<>::push_back(value_type&&) 这样的移动语义感知插入方法。
现在该怎么办?
I have a class containing a std::unique_ptr<>
and I want to put instances of this class inside of an std::map<>
. I thought one of the things that motivated the introduction of move semantics to C++ was the possibility of putting things like unique_ptrs
inside standard containers (and that really works, in the case of vectors). But it seems to me that std::map<>
doesn't like this idea. Why is this so?
#include <map>
#include <memory>
int main()
{
std::map<int,std::unique_ptr<int>> map;
// error on the line that follows (use of disabled lvalue copy constructor)
map.insert(std::make_pair(1,std::unique_ptr<int>(new int(2))));
return 0;
}
Thanks.
-- edit
Just to be more clear, the exact error messages are:
mingw32-g++.exe --std=gnu++0x -ID:\CodeEnv\Libraries\Boost -c D:\CodeEnv\CodeMess\Untitled1.cpp -o D:\CodeEnv\CodeMess\Untitled1.o
mingw32-g++.exe -o D:\CodeEnv\CodeMess\Untitled1.exe D:\CodeEnv\CodeMess\Untitled1.o
In file included from c:\mingw\bin\../lib/gcc/mingw32/4.4.1/include/c++/bits/stl_algobase.h:66,
from c:\mingw\bin\../lib/gcc/mingw32/4.4.1/include/c++/bits/stl_tree.h:62,
from c:\mingw\bin\../lib/gcc/mingw32/4.4.1/include/c++/map:60,
from D:\CodeEnv\CodeMess\Untitled1.cpp:1:
c:\mingw\bin\../lib/gcc/mingw32/4.4.1/include/c++/bits/unique_ptr.h: In copy constructor 'std::pair<const int, std::unique_ptr<int, std::default_delete<int> > >::pair(const std::pair<const int, std::unique_ptr<int, std::default_delete<int> > >&)':
c:\mingw\bin\../lib/gcc/mingw32/4.4.1/include/c++/bits/stl_pair.h:68: instantiated from 'std::_Rb_tree_node<_Val>::_Rb_tree_node(_Args&& ...) [with _Args = const std::pair<const int, std::unique_ptr<int, std::default_delete<int> > >&, _Val = std::pair<const int, std::unique_ptr<int, std::default_delete<int> > >]'
c:\mingw\bin\../lib/gcc/mingw32/4.4.1/include/c++/ext/new_allocator.h:111: instantiated from 'void __gnu_cxx::new_allocator<_Tp>::construct(_Tp*, _Args&& ...) [with _Args = const std::pair<const int, std::unique_ptr<int, std::default_delete<int> > >&, _Tp = std::_Rb_tree_node<std::pair<const int, std::unique_ptr<int, std::default_delete<int> > > >]'
c:\mingw\bin\../lib/gcc/mingw32/4.4.1/include/c++/bits/stl_tree.h:394: instantiated from 'std::_Rb_tree_node<_Val>* std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_create_node(_Args&& ...) [with _Args = const std::pair<const int, std::unique_ptr<int, std::default_delete<int> > >&, _Key = int, _Val = std::pair<const int, std::unique_ptr<int, std::default_delete<int> > >, _KeyOfValue = std::_Select1st<std::pair<const int, std::unique_ptr<int, std::default_delete<int> > > >, _Compare = std::less<int>, _Alloc = std::allocator<std::pair<const int, std::unique_ptr<int, std::default_delete<int> > > >]'
c:\mingw\bin\../lib/gcc/mingw32/4.4.1/include/c++/bits/stl_tree.h:881: instantiated from 'std::_Rb_tree_iterator<_Val> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_insert_(const std::_Rb_tree_node_base*, const std::_Rb_tree_node_base*, const _Val&) [with _Key = int, _Val = std::pair<const int, std::unique_ptr<int, std::default_delete<int> > >, _KeyOfValue = std::_Select1st<std::pair<const int, std::unique_ptr<int, std::default_delete<int> > > >, _Compare = std::less<int>, _Alloc = std::allocator<std::pair<const int, std::unique_ptr<int, std::default_delete<int> > > >]'
c:\mingw\bin\../lib/gcc/mingw32/4.4.1/include/c++/bits/stl_tree.h:1177: instantiated from 'std::pair<typename std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator, bool> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_insert_unique(const _Val&) [with _Key = int, _Val = std::pair<const int, std::unique_ptr<int, std::default_delete<int> > >, _KeyOfValue = std::_Select1st<std::pair<const int, std::unique_ptr<int, std::default_delete<int> > > >, _Compare = std::less<int>, _Alloc = std::allocator<std::pair<const int, std::unique_ptr<int, std::default_delete<int> > > >]'
c:\mingw\bin\../lib/gcc/mingw32/4.4.1/include/c++/bits/stl_map.h:500: instantiated from 'std::pair<typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename _Alloc::rebind<std::pair<const _Key, _Tp> >::other>::iterator, bool> std::map<_Key, _Tp, _Compare, _Alloc>::insert(const std::pair<const _Key, _Tp>&) [with _Key = int, _Tp = std::unique_ptr<int, std::default_delete<int> >, _Compare = std::less<int>, _Alloc = std::allocator<std::pair<const int, std::unique_ptr<int, std::default_delete<int> > > >]'
D:\CodeEnv\CodeMess\Untitled1.cpp:7: instantiated from here
c:\mingw\bin\../lib/gcc/mingw32/4.4.1/include/c++/bits/unique_ptr.h:214: error: deleted function 'std::unique_ptr<_Tp, _Tp_Deleter>::unique_ptr(const std::unique_ptr<_Tp, _Tp_Deleter>&) [with _Tp = int, _Tp_Deleter = std::default_delete<int>]'
c:\mingw\bin\../lib/gcc/mingw32/4.4.1/include/c++/bits/stl_pair.h:68: error: used here
In file included from c:\mingw\bin\../lib/gcc/mingw32/4.4.1/include/c++/map:60,
from D:\CodeEnv\CodeMess\Untitled1.cpp:1:
c:\mingw\bin\../lib/gcc/mingw32/4.4.1/include/c++/bits/stl_tree.h: In constructor 'std::_Rb_tree_node<_Val>::_Rb_tree_node(_Args&& ...) [with _Args = const std::pair<const int, std::unique_ptr<int, std::default_delete<int> > >&, _Val = std::pair<const int, std::unique_ptr<int, std::default_delete<int> > >]':
c:\mingw\bin\../lib/gcc/mingw32/4.4.1/include/c++/bits/stl_tree.h:136: note: synthesized method 'std::pair<const int, std::unique_ptr<int, std::default_delete<int> > >::pair(const std::pair<const int, std::unique_ptr<int, std::default_delete<int> > >&)' first required here
It would look like that's a problem with std::pair<>
, but it works perfectly fine when used alone:
int main()
{
std::pair<int,std::unique_ptr<int>> pair;
pair = std::make_pair(1,std::unique_ptr<int>(new int(2))); // no errors
return 0;
}
Although that obviously doesn't mean it can't be misused:
int main()
{
std::pair<int,std::unique_ptr<int>> pair1,pair2;
pair1 = std::make_pair(1,std::unique_ptr<int>(new int(2))); // no errors
pair2 = pair1; // BOOM ! Copy from lvalue
return 0;
}
which probably is what happens inside of std::map<>
.
Clues?
-- edit
Reviewing the error messages, it really happens to be a problem with TDM-GCC 4.4.1's std::map<>
implementation. It doesn't seem to feature a move semantics-aware insertion method like std::vector<>::push_back(value_type&&)
.
What to do now?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我遇到了同样的问题。通过修补bits/stl_map.h 和bits/stl_tree.h,我无需太多努力就可以添加所需的功能。为了让您的特定示例正常工作,您基本上只需向地图类添加一个 insert(value_type&&) 方法。它本质上与 insert(const value_type&) 相同,但在适当的情况下使用 std::move() 。您还必须添加正确的支持方法,但您可以使用编译错误来告诉您需要什么。
此问题已报告给 GCC 团队 (http://gcc.gnu。 org/bugzilla/show_bug.cgi?id=44436)并且有人正在研究它,所以希望我们很快就能看到对关联和无序容器中移动构造函数的支持。
I ran into the same problem. I was able to add the required functionality without too much effort by patching bits/stl_map.h and bits/stl_tree.h. To get your particular example to work, you basically just have to add an insert(value_type&&) method to the map class. It is essentially the same as insert(const value_type&), but using std::move() where appropriate. You have to add the right support methods as well, but you can use the compile errors to tell you what is needed.
This issue has been reported to the GCC team (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44436) and someone is working on it, so hopefully we will see support for move constructibles in associative and unordered containers soon.
你使用什么编译器?它可以在 VS10 beta 2 上正常编译。
编辑:有问题的编译器是 GCC
这似乎是 STL 实现中的一个错误,因为 GCC 是开源的,您可以提交修复此问题的补丁。
幸运的是,修复是在 STL 代码中而不是编译器代码中,因此应该不会太困难。
同时,您可以在本地
pair
/map
头文件中输入修复内容。What compiler are you using? It compiles fine with VS10 beta 2.
Edit: Compiler in question is GCC
This appears to be a bug in the STL implementation, since GCC is open source you can submit a patch fixing this issue.
Luckily the fix is in the STL code and not the compiler code so it shouldn't be too difficult.
In the meantime you can enter your fix in the local
pair
/map
header files.