如何方便地构造一个 unique_ptr 指向具有单个元素的向量?

How can I construct a unique_ptr pointing to a vector with single element conveniently?

我想构建一个 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 包含这些元素的向量,惯用的方法是什么?

出现在函数调用中的

{...} 不是初始化列表(除非函数明确要求 std::initializer_list);如果它被用来直接初始化某些东西(例如,在赋值的右侧,或在 range-for 循环中),它只是一个初始化列表。

如果你真的想传递一个初始化列表,你可以明确地这样做:

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 });

这将推广到任意数量的固定元素。如果你只想要一个包含三个元素的向量而不关心值,你可以使用 std::vector 的 "count" 构造函数:

auto values = std::make_unique<std::vector<std::string>>(3);
// values contains three empty strings

如果value是局部变量,可以使用iterator构造函数。否则,您可以直接使用 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] 中,然后只传递其中的 begin/end。