2010-02-18 7 views
3

У меня есть класс, содержащий std::unique_ptr<>, и я хочу поместить экземпляры этого класса внутри std::map<>. Я думал, что одна из причин, побудивших введение семантики перемещения к C++, заключалась в том, что внутри стандартных контейнеров можно было помещать такие вещи, как unique_ptrs (и это действительно работает, в случае векторов). Но мне кажется, что std::map<> не нравится эта идея. Почему это так?Невозможно создать карту MoveConstructibles

#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<>.

Улица?

- редактировать

Просмотр сообщений об ошибках, это действительно случается проблема с std::map<> реализации TDM-GCC 4.4.1 в. Кажется, что это не похоже на способ ввода семантики, например std::vector<>::push_back(value_type&&).

Что теперь делать?

+1

на ubuntu, g ++ 4.4.1 четко говорит: «error:« unique_ptr »не является членом« std »» –

+0

Вам необходимо скомпилировать ваши источники с помощью --std = C++ 0x (или --std = gnu ++ 0x, что-то в этом роде), чтобы unique_ptr был доступен из ''. Вероятно, поэтому вы видите это сообщение. Здесь unique_ptr используется отлично. Это просто беспорядок с std :: map. –

+0

Если его «карта» не может обрабатывать типы, не подлежащие копированию, это не поможет, если вы работаете только с одной проблемой. Рано или поздно вы столкнетесь с другими проблемами в другом месте. –

ответ

2

Я столкнулся с той же проблемой. Я смог добавить требуемую функциональность без особых усилий, исправив биты/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), и кто-то работает над этим, поэтому, надеюсь, вскоре мы увидим поддержку для перемещения конструкторов в ассоциативных и неупорядоченных контейнерах.

1

Какой у вас компилятор? Это нормально компилируется с VS10 бета 2.


Edit: Компилятор в вопросе GCC

Это, кажется, ошибка в реализации STL, так как GCC является открытым исходным кодом можно представить крепление патч Эта проблема.
К счастью, исправление находится в коде STL, а не в коде компилятора, поэтому это не должно быть слишком сложно.

А пока вы можете внести исправления в местные файлы pair/map.

+0

Я использую GCC 4.4.1. –

+0

Кстати, это фактически порт GCC 4.4.1 для Windows (TDM-GCC: http://www.tdragon.net/recentgcc/). –

+0

Ха-ха. Я делаю именно это сейчас. Провалился несчастно:] На самом деле я чувствовал, что слишком много вещей для исправления, поэтому я сдался. Мне просто интересно .. если бы он не был реализован в GCC и был в VC++, может быть темная причина для этого, так что ... Тем не менее, я отправил отчет об ошибках разработчикам TDM-GCC (здесь: http : //sourceforge.net/tracker/ FUNC = подробно & помощь = 2954089 & group_id = 200665 & Atid = 974439). Благодарю. –