Как я могу удобно создать unique_ptr, указывающий на вектор с одним элементом? - PullRequest
0 голосов
/ 15 февраля 2020

Я хотел бы создать unique_ptr, содержащий vector<string>, который содержит только один элемент. Возможно ли сделать это в одной строке кода? Я пробую такой подход:

auto values = make_unique<vector<string>>({value});

Но компилятор (clang ++) жалуется:

No matching function for call to 'make_unique' candidate template ignored: 
substitution failure [with _Tp = std::__1::vector<std::__1::basic_string<char>, std::__1::allocator<std::__1::basic_string<char> > >]: no type named '__unique_array_unknown_bound' in 'std::__1::__unique_if<st... candidate template ignored: substitution failure [with _Tp = std::__1::vector<std::__1::basic_string<char>, std::__1::allocator<std::__1::basic_string<char> > >]: no type named '__unique_array_known_bound' in 'std::__1::__unique_if<std:... candidate function [with _Tp = std::__1::vector<std::__1::basic_string<char>, std::__1::allocator<std::__1::basic_string<char> > >, _Args = <>] not viable: requires 0 arguments, but 1 was provided

Я не понимаю, почему он не работает, поскольку vector, очевидно, принимает использование initializer_list для строительства.

string value = ...;
auto values = vector<string>({value}); // this works

Создает unique_ptr<vector<string>> и называет его push_back единственным жизнеспособным подходом для создания такого unique_ptr?

auto values = make_unique<vector<string>>();
values->push_back(value);

В более широком смысле, если У меня есть фиксированное количество элементов (например, 3 элемента), и я хотел бы построить unique_ptr, содержащий вектор с этими элементами, как это сделать идиоматическим c способом?

Ответы [ 2 ]

2 голосов
/ 15 февраля 2020

{...}, появляющийся в вызове функции, не является списком инициализатора (если только функция явно не запрашивает std::initializer_list); это только список инициализаторов, если он используется для непосредственной инициализации чего-либо (например, в правой части назначения или в диапазоне от l oop).

Если вы действительно хотите передать список инициализатора, вы можете сделать это явно:

auto values = std::make_unique<std::vector<std::string>>(
  std::initializer_list<std::string>{ value });

Вы также можете просто создать временный вектор и передать вместо него:

auto values = std::make_unique<std::vector<std::string>>(std::vector<std::string>{ value });

Или используя C ++ 17 CTAD:

auto values = std::make_unique<std::vector<std::string>>(std::vector{ value });

Это обобщает любое количество фиксированных элементов. Если вы просто хотите вектор с тремя элементами, но не заботитесь о значениях, вы можете использовать конструктор "count" std::vector:

auto values = std::make_unique<std::vector<std::string>>(3);
// values contains three empty strings
0 голосов
/ 15 февраля 2020

Если value является локальной переменной, вы можете использовать конструктор итератора. В противном случае вы можете напрямую использовать new для использования конструктора списка инициализаторов.

using string_vec = std::vector<std::string>;

auto values = std::make_unique<string_vec>(&value, &value + 1);
auto values = std::unique_ptr<string_vec>(new string_vec{ value });

И, конечно, второй способ легко обобщается на небольшие инициализаторы фиксированного размера, такие как new string_vec{ value_1, value_2, value_3 }. При первом способе вам придется хранить их в std::string[3] и просто передавать начало / конец этого.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...