Подтвердить что ты не робот

Инициализация контейнера unique_ptrs из списка инициализаций не выполняется с помощью GCC 4.7

Я пытаюсь инициализировать std::vector<std::unique_ptr<std::string>> таким образом, который эквивалентен примеру из Bjarne Stroustrup С++ 11 FAQ:

using namespace std;
vector<unique_ptr<string>> vs { new string{"Doug"}, new string{"Adams"} }; // fails
unique_ptr<string> ps { new string{"42"} }; // OK

Я не вижу причин, по которым этот синтаксис не сработает. С этим способом инициализации контейнера что-то не так? Сообщение об ошибке компилятора огромно; соответствующий сегмент, который я нахожу, находится ниже:

/usr/lib/gcc-snapshot/lib/gcc/i686-linux-gnu/4.7.0/../../../../включают/С++/4.7.0 /bits/stl _construct.h:77:7: ошибка: нет соответствующей функции для вызова 'std::unique_ptr<std::basic_string<char> >::unique_ptr(std::basic_string<char>&)'

Как устранить эту ошибку?

4b9b3361

Ответ 1

unique_ptr конструктор explicit. Таким образом, вы не можете создать один из них с помощью new string{"foo"}. Это должно быть что-то вроде unique_ptr<string>{ new string{"foo"} }.

Что приводит нас к этому

vector<unique_ptr<string>> vs {
    unique_ptr<string>{ new string{"Doug"} },
    unique_ptr<string>{ new string{"Adams"} }
};

Однако он может протекать, если один из конструкторов терпит неудачу. Безопаснее использовать make_unique:

vector<unique_ptr<string>> vs {
     make_unique<string>("Doug"),
     make_unique<string>("Adams")
};

Но... initializer_list всегда выполняет копии, а unique_ptr не копируются. Это действительно раздражает списки инициализаторов. Вы можете взломать его или вернуться к инициализации с помощью вызовов emplace_back.

Если вы действительно управляете string с помощью интеллектуальных указателей, и это не только для примера, тогда вы можете сделать еще лучше: просто сделайте vector<string>. std::string уже обрабатывает ресурсы, которые он использует.

Ответ 2

После "исправления" вашего примера:

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

У меня появилось очень четкое сообщение об ошибке:

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>*]'

Эта ошибка говорит о невозможности использования явного конструктора unique_ptr.