[英]Is `std::array<T, 0>` default constructible where `T` is not default constructible?
Consider the code below: 考虑下面的代码:
#include <array>
struct T
{
T() = delete;
};
int main()
{
std::array<T, 0> a;
a.size();
}
We default initialize a 0-sized array. 我们默认初始化一个0大小的数组。 Since there's no elements, no constructor of
T
should be called. 由于没有元素,因此不应调用
T
构造函数。
However, Clang still requires T
to be default constructible, while GCC accepts the code above. 但是, Clang仍然要求
T
是默认可构造的,而GCC接受上面的代码。
Note that if we change the array initialization to: 请注意,如果我们将数组初始化更改为:
std::array<T, 0> a{};
Clang accepts it this time. Clang这次接受了。
Does non-default-constructible T
prevent std::array<T, 0>
from being default-constructible? 非默认可构造的
T
是否会阻止std::array<T, 0>
成为默认可构造的?
Since there's no elements, no constructor of T should be called.
由于没有元素,因此不应调用T的构造函数。
Does non-default-constructible T preventstd::array<T, 0>
from being default-constructible?非默认可构造的T是否会阻止
std::array<T, 0>
成为默认可构造的?
The standard doesn't specify what layout std::array<T, 0>
should have for us to answer that. 该标准没有指定
std::array<T, 0>
应该具有什么布局才能让我们回答。 The zero sized array specialization is only said to behave as follows: 零大小数组专门化仅表现如下:
1 array shall provide support for the special case N == 0.
1个数组应为特殊情况N == 0提供支持。
2 In the case that N == 0, begin() == end() == unique value.2在N == 0的情况下,begin()== end()==唯一值。 The return value of data() is unspecified.
data()的返回值未指定。
3 The effect of calling front() or back() for a zero-sized array is undefined.3为零大小的数组调用front()或back()的效果是不确定的。
4 Member function swap() shall have a non-throwing exception specification.4成员函数swap()应具有非抛出异常规范。
The behavior you note is most probably due to differences in implementation alone. 您注意到的行为很可能仅是由于实现上的差异。
Thanks to @TC, as pointed out in his comment , it's addressed in LWG 2157 , which is still an open issue as of this writing. 感谢@TC,正如他在评论中所指出的那样,该问题已在LWG 2157中得到解决,在撰写本文时仍是一个未解决的问题。
The proposed resolution adds this bullet point (emphasis mine): 拟议的决议增加了这一要点(强调我的意思):
The unspecified internal structure of array for this case shall allow initializations like:
对于这种情况,未指定的数组内部结构应允许初始化,例如:
array<T, 0> a = { };
and said initializations must be valid even when T is not default-constructible .
并且即使T是不可缺省构造的 ,所述初始化也必须有效。
So it's clear that the intended behavior is to have std::array<T, 0>
default constructible even when T is not. 因此很明显,预期的行为是使
std::array<T, 0>
默认可构造,即使T不是。
This question explains what happens with clang and std::array
Deleted default constructor. 这个问题解释了clang和
std::array
删除默认构造函数会发生什么。 Objects can still be created... sometimes 仍然可以创建对象...有时
But with gcc
the difference comes from the library code. 但是与
gcc
的区别来自库代码。 There is indeed a specific implementation detail in the gcc codebase that is relevant to this question as @StoryTeller mentioned 确实在gcc代码库中有一个与该问题相关的具体实现细节,如@StoryTeller所述
gcc has a special case for std::array
with a size of 0, see the following code from their <array>
header (from gcc 5.4.0
) gcc对于大小为0的
std::array
有特殊情况,请参见其<array>
头中的以下代码(来自gcc 5.4.0
)
template<typename _Tp, std::size_t _Nm>
struct __array_traits
{
typedef _Tp _Type[_Nm];
static constexpr _Tp&
_S_ref(const _Type& __t, std::size_t __n) noexcept
{ return const_cast<_Tp&>(__t[__n]); }
static constexpr _Tp*
_S_ptr(const _Type& __t) noexcept
{ return const_cast<_Tp*>(__t); }
};
template<typename _Tp>
struct __array_traits<_Tp, 0>
{
struct _Type { };
static constexpr _Tp&
_S_ref(const _Type&, std::size_t) noexcept
{ return *static_cast<_Tp*>(nullptr); }
static constexpr _Tp*
_S_ptr(const _Type&) noexcept
{ return nullptr; }
};
as you can see, there is a specialization of __array_traits
(which is used in std::array
for the underlying array) when the array size is 0, that doesn't even have an array of the type it's templated on. 如您所见,当数组大小为0时,
__array_traits
被特殊化(用于基础数组的std::array
中),甚至没有其模板化类型的数组。 The type _Type
is not an array, but an empty struct! _Type
类型不是数组,而是空结构!
That is why there are no constructors invoked. 这就是为什么没有调用构造函数的原因。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.