c++ - El contenedor de inicialización de unique_ptrs de la lista de inicializadores falla con GCC 4.7
compiler-errors initialization (2)
Después de "arreglar" tu ejemplo:
#include <vector>
#include <memory>
#include <string>
int main()
{
std::vector<std::unique_ptr<std::string>> vs = { { new std::string{"Doug"} }, { new std::string{"Adams"} } }; // fails
std::unique_ptr<std::string> ps { new std::string{"42"} }; // OK
}
Tengo un mensaje de error muy claro:
error: converting to ''std::unique_ptr<std::basic_string<char> >'' from initializer list would use explicit constructor ''std::unique_ptr<_Tp, _Dp>::unique_ptr(std::unique_ptr<_Tp, _Dp>::pointer) [with _Tp = std::basic_string<char>, _Dp = std::default_delete<std::basic_string<char> >, std::unique_ptr<_Tp, _Dp>::pointer = std::basic_string<char>*]''
Este error indica que no es posible utilizar el contructor explícito de unique_ptr
.
Estoy tratando de inicializar un std::vector<std::unique_ptr<std::string>>
de una manera que es equivalente a un ejemplo de C ++ 11 de Bjarne Stroustrup :
using namespace std;
vector<unique_ptr<string>> vs { new string{"Doug"}, new string{"Adams"} }; // fails
unique_ptr<string> ps { new string{"42"} }; // OK
No veo ninguna razón por la que esta sintaxis deba fallar. ¿Hay algo malo con esta forma de inicializar el contenedor?
El mensaje de error del compilador es enorme; El segmento relevante que encuentro está abajo:
/usr/lib/gcc-snapshot/lib/gcc/i686-linux-gnu/4.7.0/../../../../include/c++/4.7.0 /bits/stl_construct.h:77 : 7: error: no hay función coincidente para la llamada a
''std::unique_ptr<std::basic_string<char> >::unique_ptr(std::basic_string<char>&)''
¿Cuál es la manera de solucionar este error?
El constructor de unique_ptr
es explicit
. Entonces no puedes crear uno implícitamente con una new string{"foo"}
. Debe ser algo como unique_ptr<string>{ new string{"foo"} }
.
Lo que nos lleva a esto.
// not good
vector<unique_ptr<string>> vs {
unique_ptr<string>{ new string{"Doug"} },
unique_ptr<string>{ new string{"Adams"} }
};
Sin embargo, puede filtrarse si falla uno de los constructores. Es más seguro usar make_unique
:
// does not work
vector<unique_ptr<string>> vs {
make_unique<string>("Doug"),
make_unique<string>("Adams")
};
Pero ... initializer_list
s siempre realiza copias, y unique_ptr
s no son copiables. Esto es algo realmente molesto acerca de las listas de inicialización. Puede hackearlo o retroceder a la inicialización con llamadas a emplace_back
.
Si realmente está administrando string
con punteros inteligentes y no es solo para el ejemplo, puede hacerlo aún mejor: simplemente haga un vector<string>
. La std::string
ya maneja los recursos que usa.