Wal*_*ter 11 c++ default-constructor stdvector c++11
在C++ 11中,有两个版本std::vector::resize():
void resize( size_type count );
void resize( size_type count, const value_type& value);
Run Code Online (Sandbox Code Playgroud)
我理解(正如对该问题的答案之一的评论之一所建议的),第一个要求value_type是默认可构造的,而第二个要求它是可复制构造的.但是,(gcc 4.7.0)
using namespace std;
typedef int block[4];
vector<block> A;
static_assert(is_default_constructible<block>::value,";-("); // does not fire
A.resize(100); // compiler error
Run Code Online (Sandbox Code Playgroud)
所以要么我的理解是错误的,要么gcc是错误的.哪一个?
eca*_*mur 10
关于vector.resize(n)格式良好的要求(23.3.6.3:10)T应该是CopyInsertable,即以下应该是格式良好的(23.2.1:13):
allocator_traits<A>::construct(m, p, v);
Run Code Online (Sandbox Code Playgroud)
其中A是向量的分配器类型,m是分配器,p属于类型T *且v属于类型T.
正如您在20.6.8.2:5中发现的那样,这对于一般情况下的数组类型是无效的,因为它等同于调用
::new(static_cast<void *>(p))block(v);
Run Code Online (Sandbox Code Playgroud)
这对于数组类型无效(数组不能通过括号初始化).
实际上,你是正确的,g ++有一个bug; 它总是可以CopyInsertable通过提供适当的分配器来解决这个问题,但是g ++不能允许这样做:
#include <vector>
template<typename T, int n> struct ArrayAllocator: std::allocator<T[n]> {
void construct(T (*p)[n], T (&v)[n]) {
for (int i = 0; i < n; ++i)
::new(static_cast<void *>(p + i)) T{v[i]};
}
};
int main() {
std::vector<int[4], ArrayAllocator<int, 4>> c;
c.resize(100); // fails
typedef ArrayAllocator<int, 4> A;
A m;
int (*p)[4] = 0, v[4];
std::allocator_traits<A>::construct(m, p, v); // works
}
Run Code Online (Sandbox Code Playgroud)
另一个错误在于标准本身; 20.9.4.3:3指定std::is_default_constructible<T> 为等效于std::is_constructible<T>,其中20.9.4.3:6指定std::is_constructible<T, Args...>为良好形成标准T t(std::declval<Args>()...),对数组类型有效(如@Johannes Schaub-litb指出的,数组类型可以初始化(zero-pack-expansion)).然而,17.6.3.1:2需要DefaultConstructible除了该T()很好地形成的,这是不用于阵列型的情况下T,但不被选中std::is_default_constructible.