|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Member
Iscritto dal: Nov 2010
Messaggi: 211
|
[C++] Uniform initialization syntax per mappa con unique_ptr
Salve, volevo gentilmente sapere per quale motivo il seguente codice non è corretto nel caso in cui si usi uno smart pointer con la sintassi di inizializzazione uniforme. Se la mappa contenesse un puntatore normale, allora funzionerebbe anche con la nuova sintassi.
Codice:
#include <map>
#include <memory>
using namespace std;
int main() {
map<string, unique_ptr<Test> > a;
a.insert({ //non funziona
string("a"),
unique_ptr<Test>(new Test())
});
a.insert(make_pair( //funziona
string("a"),
unique_ptr<Test>(new Test())
));
return 0;
}
Codice:
map<string, unique_ptr<Test> > a = {
{"a", new Test()},
{"b", new Test()},
{...}
}
Codice:
16:41:43 **** Incremental Build of configuration Debug for project test ****
make all
Building file: ../src/test.cpp
Invoking: Cross G++ Compiler
g++ -D__cplusplus=201103L -O0 -g3 -Wall -c -fmessage-length=0 -std=c++11 -MMD -MP -MF"src/test.d" -MT"src/test.d" -o "src/test.o" "../src/test.cpp"
In file included from c:/MinGW64/x86_64-w64-mingw32/include/c++/x86_64-w64-mingw32/bits/c++allocator.h:33:0,
from c:/MinGW64/x86_64-w64-mingw32/include/c++/bits/allocator.h:46,
from c:/MinGW64/x86_64-w64-mingw32/include/c++/string:41,
from c:/MinGW64/x86_64-w64-mingw32/include/c++/bits/locale_classes.h:40,
from c:/MinGW64/x86_64-w64-mingw32/include/c++/bits/ios_base.h:41,
from c:/MinGW64/x86_64-w64-mingw32/include/c++/ios:42,
from c:/MinGW64/x86_64-w64-mingw32/include/c++/ostream:38,
from c:/MinGW64/x86_64-w64-mingw32/include/c++/iostream:39,
from ../src/test.cpp:9:
c:/MinGW64/x86_64-w64-mingw32/include/c++/ext/new_allocator.h: In instantiation of 'void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = std::pair<const std::basic_string<char>, std::unique_ptr<Test> >; _Args = {const std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::unique_ptr<Test, std::default_delete<Test> > >&}; _Tp = std::_Rb_tree_node<std::pair<const std::basic_string<char>, std::unique_ptr<Test> > >]':
c:/MinGW64/x86_64-w64-mingw32/include/c++/bits/alloc_traits.h:253:4: required from 'static std::_Require<typename std::allocator_traits<_Alloc>::__construct_helper<_Tp, _Args>::type> std::allocator_traits<_Alloc>::_S_construct(_Alloc&, _Tp*, _Args&& ...) [with _Tp = std::pair<const std::basic_string<char>, std::unique_ptr<Test> >; _Args = {const std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::unique_ptr<Test, std::default_delete<Test> > >&}; _Alloc = std::allocator<std::_Rb_tree_node<std::pair<const std::basic_string<char>, std::unique_ptr<Test> > > >; std::_Require<typename std::allocator_traits<_Alloc>::__construct_helper<_Tp, _Args>::type> = void]'
c:/MinGW64/x86_64-w64-mingw32/include/c++/bits/alloc_traits.h:399:57: required from 'static decltype (_S_construct(__a, __p, (forward<_Args>)(std::allocator_traits::construct::__args)...)) std::allocator_traits<_Alloc>::construct(_Alloc&, _Tp*, _Args&& ...) [with _Tp = std::pair<const std::basic_string<char>, std::unique_ptr<Test> >; _Args = {const std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::unique_ptr<Test, std::default_delete<Test> > >&}; _Alloc = std::allocator<std::_Rb_tree_node<std::pair<const std::basic_string<char>, std::unique_ptr<Test> > > >; decltype (_S_construct(__a, __p, (forward<_Args>)(std::allocator_traits::construct::__args)...)) = <type error>]'
c:/MinGW64/x86_64-w64-mingw32/include/c++/bits/stl_tree.h:423:42: required from 'std::_Rb_tree_node<_Val>* std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_create_node(_Args&& ...) [with _Args = {const std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::unique_ptr<Test, std::default_delete<Test> > >&}; _Key = std::basic_string<char>; _Val = std::pair<const std::basic_string<char>, std::unique_ptr<Test> >; _KeyOfValue = std::_Select1st<std::pair<const std::basic_string<char>, std::unique_ptr<Test> > >; _Compare = std::less<std::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::basic_string<char>, std::unique_ptr<Test> > >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type = std::_Rb_tree_node<std::pair<const std::basic_string<char>, std::unique_ptr<Test> > >*]'
c:/MinGW64/x86_64-w64-mingw32/include/c++/bits/stl_tree.h:1143:66: required from 'std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_insert_(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Base_ptr, std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Base_ptr, _Arg&&) [with _Arg = const std::pair<const std::basic_string<char>, std::unique_ptr<Test> >&; _Key = std::basic_string<char>; _Val = std::pair<const std::basic_string<char>, std::unique_ptr<Test> >; _KeyOfValue = std::_Select1st<std::pair<const std::basic_string<char>, std::unique_ptr<Test> > >; _Compare = std::less<std::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::basic_string<char>, std::unique_ptr<Test> > >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator = std::_Rb_tree_iterator<std::pair<const std::basic_string<char>, std::unique_ptr<Test> > >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Base_ptr = std::_Rb_tree_node_base*]'
c:/MinGW64/x86_64-w64-mingw32/include/c++/bits/stl_tree.h:1502:38: required from 'std::pair<std::_Rb_tree_iterator<_Val>, bool> std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_insert_unique(_Arg&&) [with _Arg = const std::pair<const std::basic_string<char>, std::unique_ptr<Test> >&; _Key = std::basic_string<char>; _Val = std::pair<const std::basic_string<char>, std::unique_ptr<Test> >; _KeyOfValue = std::_Select1st<std::pair<const std::basic_string<char>, std::unique_ptr<Test> > >; _Compare = std::less<std::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::basic_string<char>, std::unique_ptr<Test> > >]'
c:/MinGW64/x86_64-w64-mingw32/include/c++/bits/stl_map.h:627:37: required from 'std::pair<typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename __gnu_cxx::__alloc_traits<_Alloc>::rebind<std::pair<const _Key, _Tp> >::other>::iterator, bool> std::map<_Key, _Tp, _Compare, _Alloc>::insert(const value_type&) [with _Key = std::basic_string<char>; _Tp = std::unique_ptr<Test>; _Compare = std::less<std::basic_string<char> >; _Alloc = std::allocator<std::pair<const std::basic_string<char>, std::unique_ptr<Test> > >; typename std::_Rb_tree<_Key, std::pair<const _Key, _Tp>, std::_Select1st<std::pair<const _Key, _Tp> >, _Compare, typename __gnu_cxx::__alloc_traits<_Alloc>::rebind<std::pair<const _Key, _Tp> >::other>::iterator = std::_Rb_tree_iterator<std::pair<const std::basic_string<char>, std::unique_ptr<Test> > >; std::map<_Key, _Tp, _Compare, _Alloc>::value_type = std::pair<const std::basic_string<char>, std::unique_ptr<Test> >]'
../src/test.cpp:42:3: required from here
c:/MinGW64/x86_64-w64-mingw32/include/c++/ext/new_allocator.h:120:4: error: use of deleted function 'constexpr std::pair<_T1, _T2>::pair(const std::pair<_T1, _T2>&) [with _T1 = const std::basic_string<char>; _T2 = std::unique_ptr<Test>]'
{ ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
^
In file included from c:/MinGW64/x86_64-w64-mingw32/include/c++/bits/stl_algobase.h:64:0,
from c:/MinGW64/x86_64-w64-mingw32/include/c++/bits/char_traits.h:39,
from c:/MinGW64/x86_64-w64-mingw32/include/c++/ios:40,
from c:/MinGW64/x86_64-w64-mingw32/include/c++/ostream:38,
from c:/MinGW64/x86_64-w64-mingw32/include/c++/iostream:39,
from ../src/test.cpp:9:
c:/MinGW64/x86_64-w64-mingw32/include/c++/bits/stl_pair.h:127:17: note: 'constexpr std::pair<_T1, _T2>::pair(const std::pair<_T1, _T2>&) [with _T1 = const std::basic_string<char>; _T2 = std::unique_ptr<Test>]' is implicitly deleted because the default definition would be ill-formed:
constexpr pair(const pair&) = default;
^
c:/MinGW64/x86_64-w64-mingw32/include/c++/bits/stl_pair.h:127:17: error: use of deleted function 'std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = Test; _Dp = std::default_delete<Test>]'
In file included from c:/MinGW64/x86_64-w64-mingw32/include/c++/memory:81:0,
from ../src/test.cpp:13:
c:/MinGW64/x86_64-w64-mingw32/include/c++/bits/unique_ptr.h:356:7: note: declared here
unique_ptr(const unique_ptr&) = delete;
^
make: *** [src/test.o] Error 1
Ultima modifica di biowep : 15-11-2014 alle 16:44. |
|
|
|
|
|
#2 |
|
Senior Member
Iscritto dal: Jan 2012
Messaggi: 1267
|
Mi pare sia dovuto al fatto che std::unique_ptr<T> non è copiabile ma solo movable, e con la prima sintassi crei un unique_ptr che viene passato ad insert per const reference, causando la chiamata al copy constructor. make_pair invece crea un std:
|
|
|
|
|
|
#3 | |
|
Senior Member
Iscritto dal: May 2001
Messaggi: 12883
|
Quote:
Unique Ptr è studiato per evitare la copia (altrimenti non sarebbe più un unique pointer). Al posto di fare insert puoi provare emplace: Codice:
...
map<string, unique_ptr<int>> a;
a.emplace("a", unique_ptr<int>(new int(4)));
...
Codice:
...
map<string, unique_ptr<int>> a;
a.emplace("a", make_unique<int>(4));
...
|
|
|
|
|
|
|
#4 |
|
Member
Iscritto dal: Nov 2010
Messaggi: 211
|
Ma se, da quel che leggo nella documentazione, map::emplace prende degli argomenti e costruisce gli oggetti direttamente, perché allora non posso fare:
Codice:
map<string, unique_ptr<int>> a;
a.emplace("a", new int(4));
|
|
|
|
|
|
#5 | |
|
Senior Member
Iscritto dal: May 2001
Messaggi: 12883
|
Quote:
Codice:
/usr/include/c++/4.9.2/bits/stl_pair.h:112:26: note: no known conversion for argument 2 from ‘int*’ to ‘const std::unique_ptr<int>&’ /usr/include/c++/4.9.2/bits/stl_pair.h:108:26: note: constexpr std::pair<_T1, _T2>::pair() [with _T1 = const std::basic_string<char>; _T2 = std::unique_ptr<int>] La costruzione di un oggetto a partire dal solo parametro del costruttore può funzionare solo se lì viene richiesto un oggetto e non un suo reference. Ultima modifica di WarDuck : 15-11-2014 alle 18:50. |
|
|
|
|
|
|
#6 |
|
Member
Iscritto dal: Nov 2010
Messaggi: 211
|
Quindi sarebbe una mancanza della classe unique_ptr?
Grazie delle risposte, credo che d'ora in poi userò emplace invece che insert, sembra più efficiente da quel che leggo. |
|
|
|
|
|
#7 | |
|
Senior Member
Iscritto dal: May 2001
Messaggi: 12883
|
Quote:
http://www.cplusplus.com/reference/utility/pair/pair/ In soldoni lui si aspetta che gli oggetti siano già stati costruiti precedentemente. La costruzione dell'oggetto "implicita" avrebbe funzionato se il prototipo fosse stato: Codice:
pair(T a, T b); Ultima modifica di WarDuck : 16-11-2014 alle 13:38. |
|
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 06:45.




















