5

请参阅转发参数时应该使用 () 还是 {}?. foo是一个std::vector克隆。

在 N4140 中,unique.ptr.create std::make_unique被指定为:

template <class T, class... Args> unique_ptr<T> make_unique(Args&&... args);

  • 备注T:除非不是数组,否则此函数不应参与重载决议。

  • 回报unique_ptr<T>(new T(std::forward<Args>(args)...))

这意味着实现需要使用()而不是{}初始化对象。例如,以下

auto s1 = std::make_unique<foo>(3, 1).get()->size();
auto s2 = std::make_unique<foo>(1).get()->size();
auto s3 = std::make_unique<foo>(2).get()->size();
std::cout << s1 << s2 << s3;

输出312而 if {}(inside std::make_unique) 被使用211将被输出。因为初始化器列表无法推导出来,所以std::initializer_list必须显式传递才能得到后者的结果。问题是,为什么不提供这样的重载?

namespace test
{

template <class T, class Deduce>
std::unique_ptr<T> make_unique(std::initializer_list<Deduce> li)
{
    return ::std::make_unique<T>(li);
}

};

int main()
{
    auto p1 = test::make_unique<foo>({3, 1}).get()->size();
    auto p2 = test::make_unique<foo>({1}).get()->size();
    auto p3 = test::make_unique<foo>({2}).get()->size();
    std::cout << p1 << p2 << p3;
}

输出211

我不认为“您可以自己编写”或“避免使标准臃肿”的原因是很好的理由。提供这种过载有什么缺点吗?

4

2 回答 2

2

我不知道完整的历史,但最有可能的答案是“没有人提议”。

std::make_unique仅在 C++14 中添加但std::unique_ptr在 C++11 中存在的事实支持了这一点。

的代码和建议std::make_shared(最终反映在 中)在支持它的初始化语法make_unique之前(在 boost 中)存在。initializer_list

您现在可以做的一件事是提出它(如果有的话,解决极端情况,例如,如果目标类型不支持,则使用 SFINAE 删除重载initializer_list)。

于 2016-05-11T11:26:16.207 回答
0

我认为这只是一个模板扣除问题,请参阅this answer

你可以试试这些:

int main()
{
    auto p1 = std::make_unique<foo>(std::initializer_list<int>{3, 1}).get()->size();
    auto p2 = std::make_unique<foo>(foo{1}).get()->size();
    auto l3 = {2};
    auto p3 = std::make_unique<foo>(l3).get()->size();
    std::cout << p1 << p2 << p3;
}
于 2016-05-11T11:38:31.207 回答