为什么'make_unique< T [N]>`不允许? [英] Why is `make_unique<T[N]>` disallowed?
问题描述
假设命名空间 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)...)。
$ c> T 是未知边界的数组。
类T> unique_ptr< T>备注:此函数不应参与重载解析,除非<$ c <$ p <$>
4 返回:unique_ptr< T>(new typename remove_extent< T> :: type [n]())。
Args> unspecified make_unique(Args& ...)= delete;
5 备注:参与重载解决,除非
T
是已知边界的数组。
,这在我看来是像泥一样清楚,我认为它需要更多的博览会。但是,除了编辑评论,我相信我已经解释了每个变种的含义:
-
template< class T,class ... Args> unique_ptr< T> make_unique(Args& ... args);
您的bog标准
make_unique
非数组类型。推测remark表示某些形式的静态断言或SFINAE技巧是防止当T
是数组类型时,模板被成功实例化。
在高层,将它看作等同于
T * ptr = new T(args);
的智能指针。 p> -
模板< class T> unique_ptr< T> make_unique(size_t n);
数组类型的变体。创建动态分配的数组
n
×Ts
,并返回它包装在unique_ptr
。
在高层,将它看作等同于
T * ptr = new T [n];
的智能指针。 -
模板< 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:
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 whenT
is an array type.At a high-level, see it as the smart-pointer equivalent to
T* ptr = new T(args);
.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 aunique_ptr<T[]>
.At a high-level, see it as the smart-pointer equivalent to
T* ptr = new T[n];
.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]
(whereN
is someconstexpr
) then, well, why? Wouldn't it be completely possible for aunique_ptr<T[N]>
to exist that wraps a dynamically-allocated block ofN
×T
s? Would this be such a bad thing, to the extent that the committee has gone out of its way to disallow its creation usingmake_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 forT[N]
. However, users will be strongly tempted to writemake_unique<T[N]>()
. This is a no-win scenario. Returningunique_ptr<T[N]>
would select the primary template for single objects, which is bizarre. Returningunique_ptr<T[]>
would be an exception to the otherwise ironclad rule thatmake_unique<something>()
returnsunique_ptr<something>
. Therefore, this proposal makesT[N]
ill-formed here, allowing implementations to emit helpfulstatic_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< T [N]>`不允许?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!