为什么'make_unique< T [N]>`不允许? [英] Why is `make_unique<T[N]>` disallowed?

查看:147
本文介绍了为什么'make_unique< T [N]>`不允许?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设命名空间 std



C ++ 14委员会草案N3690定义 std :: make_unique


n3690:20.9.1.4]: unique_ptr 创建    create]



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



1 备注:此函数不得参与重载分辨率除非 T 不是数组。

2 返回: unique_ptr< T> new T(std :: forward< Args>(args)...)。



类T> unique_ptr< T>备注:此函数不应参与重载解析,除非<$ c <$ p <$>

$ c> T 是未知边界的数组。

4 返回: unique_ptr< T>(new typename remove_extent< T> :: type [n]())。



Args> unspecified make_unique(Args& ...)= delete;



5 备注:参与重载解决,除非 T 是已知边界的数组。


,这在我看来是像泥一样清楚,我认为它需要更多的博览会。但是,除了编辑评论,我相信我已经解释了每个变种的含义:


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



    您的bog标准 make_unique 非数组类型。推测remark表示某些形式的静态断言或SFINAE技巧是防止当 T 是数组类型时,模板被成功实例化。



    在高层,将它看作等同于 T * ptr = new T(args); 的智能指针。 p>


  2. 模板< class T> unique_ptr< T> make_unique(size_t n);



    数组类型的变体。创建动态分配的数组 n × Ts ,并返回它包装在 unique_ptr



    在高层,将它看作等同于 T * ptr = new T [n]; 的智能指针。


  3. 模板< class T,class ... Args>未指定的make_unique(Args& ...)



    不允许。 可能会 unique_ptr< T [N]>



    否则为智能指针等同于无效 T [N] * ptr = new(keep_the_dimension_please)(the_dimension_is_constexpr)T [N];


首先,我是否正确?如果是,第三个函数是怎么回事?




  • 如果不允许程序员试图动态分配一个数组,同时为每个元素提供构造函数参数(就像 new int [5](args)是不可能的),那么第一个函数不能


  • 如果它是为了防止添加到 T [ N] * ptr = new T [N] (其中 N 是某些 constexpr 那么,为什么?不能完全可能存在包含 N unique_ptr c $ c>× T s?这将是一件坏事,因为委员会已经使用 make_unique




为什么 make_unique< T [N]> 不允许? / p>

解决方案

引用原始提案


T [N]



自N3485起, unique_ptr 不提供 T [N]
然而,用户会强烈地想写 make_unique< T [N]>()。这
是一个没有胜利的场景。返回 unique_ptr< T [N]> 将为单个对象选择主
模板,这很奇怪。返回 unique_ptr< T []>
将是除此之外的铁饼规则的一个例外
make_unique< something& )返回 unique_ptr< something> 。因此,这个
提议使得 T [N] 不合格,允许实现释放
有帮助 static_assert 消息。


提案的作者Stephan T. Lavavej在此视频在Core C ++ (由 chris ),从分钟1:01:10开始(或多或少)。


Assume namespace std throughout.

The C++14 committee draft N3690 defines std::make_unique thus:

[n3690: 20.9.1.4]: unique_ptr creation    [unique.ptr.create]

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

1 Remarks: This function shall not participate in overload resolution unless T is not an array.
2 Returns: unique_ptr<T>(new T(std::forward<Args>(args)...)).

template <class T> unique_ptr<T> make_unique(size_t n);

3 Remarks: This function shall not participate in overload resolution unless T is an array of unknown bound.
4 Returns: unique_ptr<T>(new typename remove_extent<T>::type[n]()).

template <class T, class... Args> unspecified make_unique(Args&&...) = delete;

5 Remarks: This function shall not participate in overload resolution unless T is an array of known bound.

Now, this seems to me to be about as clear as mud, and I think it needs more exposition. But, this editorial comment aside, I believe I've decoded the meanings of each variant:

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

    Your bog-standard make_unique for non-array types. Presumably the "remark" indicates that some form of static assertion or SFINAE trick is to prevent the template from being successfully instantiated when T is an array type.

    At a high-level, see it as the smart-pointer equivalent to T* ptr = new T(args);.

  2. template <class T> unique_ptr<T> make_unique(size_t n);

    A variant for array types. Creates a dynamically-allocated array of n × Ts, and returns it wrapped in a unique_ptr<T[]>.

    At a high-level, see it as the smart-pointer equivalent to T* ptr = new T[n];.

  3. template <class T, class... Args> unspecified make_unique(Args&&...)

    Disallowed. "unspecified" would probably be unique_ptr<T[N]>.

    Would otherwise be the smart-pointer equivalent to something like the invalid T[N]* ptr = new (keep_the_dimension_please) (the_dimension_is_constexpr) T[N];.

First of all, am I correct? And, if so, what's going on with the third function?

  • If it's there to disallow programmers from attempting to dynamically-allocate an array while providing constructor arguments for each element (just as new int[5](args) is impossible), then that's already covered by the fact that the first function cannot be instantiated for array types, isn't it?

  • If it's there to prevent the addition to the language of a construct like T[N]* ptr = new T[N] (where N is some constexpr) then, well, why? Wouldn't it be completely possible for a unique_ptr<T[N]> to exist that wraps a dynamically-allocated block of N × Ts? Would this be such a bad thing, to the extent that the committee has gone out of its way to disallow its creation using make_unique?

Why is make_unique<T[N]> disallowed?

解决方案

Quoting from the original proposal:

T[N]

As of N3485, unique_ptr doesn't provide a partial specialization for T[N]. However, users will be strongly tempted to write make_unique<T[N]>(). This is a no-win scenario. Returning unique_ptr<T[N]> would select the primary template for single objects, which is bizarre. Returning unique_ptr<T[]> would be an exception to the otherwise ironclad rule that make_unique<something>() returns unique_ptr<something>. Therefore, this proposal makes T[N] ill-formed here, allowing implementations to emit helpful static_assert messages.

The author of the proposal, Stephan T. Lavavej, illustrates this situation in this video on Core C++ (courtesy of chris), starting from minute 1:01:10 (more or less).

这篇关于为什么'make_unique&lt; T [N]&gt;`不允许?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆