我尝试使用std::make_unique
来实例化一个类,其构造函数将接收std::initializer_list
。这是一个最小的案例:
#include <string>
#include <vector>
#include <initializer_list>
#include <memory>
struct Foo {
Foo(std::initializer_list<std::string> strings) : strings(strings) {}
std::vector<std::string> strings;
};
int main(int, char**) {
auto ptr = std::make_unique<Foo>({"Hello", "World"});
return 0;
}
您可以在Coliru上看到它没有构建:
main.cpp:14:56: error: no matching function for call to 'make_unique(<brace-enclosed initializer list>)'
auto ptr = std::make_unique<Foo>({"Hello", "World"});
那么,据说make_unique
无法使用initializer_list
? GCC 4.9.1中有错误吗?或者我忽略了什么?
答案 0 :(得分:30)
std::make_unique
是一个函数模板,它推导出传递给对象构造函数的参数类型。遗憾的是,支撑列表不可推导(auto
声明除外),因此在缺少参数类型时无法实例化函数模板。
你可以不使用std::make_unique
,但请不要走那条路 - 为了孩子们的缘故,你应该尽可能地避免裸new
。或者,您可以通过指定类型来进行类型推导:
std::make_unique<Foo>(std::initializer_list<std::string>({"Hello", "World"}))
std::make_unique<Foo, std::initializer_list<std::string>>({"Hello", "World"})
auto il = { "Hello"s, "World"s }; auto ptr = std::make_unique<Foo>(il);
最后一个选项使用auto
声明的特殊规则,(正如我上面所说) do 实际上推导出std::initializer_list
。
答案 1 :(得分:3)
如果你准备输入一些额外的字符,你可以这样做:
auto ptr = std::make_unique<Foo>( make_init_list( { "Hello"s , "World"s } ));
其中init_list
定义为
template<typename T>
std:: initializer_list<T> make_init_list ( std:: initializer_list<T> && l ) {
return l;
}
这允许进行演绎,如果代码中有许多地方你必须这样做,这是很方便的。
(适用于clang 3.9和gcc 6.2.0。除了我必须调整std::string
- 文字并更改为make_shared
之外,我还可以使用g ++ - 4.8.4。在T
内make_init_list
的扣除工作正常。)
实际上,这是一个延伸吗?是否成功扣除了标准所要求的make_init_list
?