通过make_unique/make_shared调用initializer_list构造函数

Que*_*tin 27 c++ initializer-list unique-ptr c++14

我试图用来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;
}
Run Code Online (Sandbox Code Playgroud)

您可以在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"});
Run Code Online (Sandbox Code Playgroud)

那么,make_unique据说无法使用initializer_lists?GCC 4.9.1中有错误吗?或者我忽略了什么?

Ker*_* SB 38

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的声明,这(正如我上面所暗示的)其实演绎的std::initializer_list.


Aar*_*aid 7

如果您准备输入一些额外的字符,您可以这样做:

auto ptr = std::make_unique<Foo>( make_init_list( { "Hello"s , "World"s } ));
Run Code Online (Sandbox Code Playgroud)

其中init_list定义为

template<typename T>
std:: initializer_list<T> make_init_list ( std:: initializer_list<T> && l ) {
    return l;
}
Run Code Online (Sandbox Code Playgroud)

这允许进行推导,如果代码中有很多地方必须执行此操作,则很方便。

(文选铛3.9和gcc 6.2.0我把它给了相对于g ++工作- 4.8.4还,但我不得不把调整std::string-literal和变化make_shared,但扣除。Tmake_init_list工作得很好。)

其实,这是一个扩展?成功扣除是否make_init_list符合标准要求?