在C ++ 11中,有两个版本 std::vector::resize()
:
void resize( size_type count );
void resize( size_type count, const value_type& value);
我明白了(正如其中一个评论所建议的那样 这个问题)第一个要求 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
所以要么我的理解是错误的,要么gcc是错误的。哪一个?
要求(23.3.6.3:10) vector.resize(n)
形式良好的是 T
应该 CopyInsertable
,即以下应该是格式良好的(23.2.1:13):
allocator_traits<A>::construct(m, p, v);
哪里 A
是向量的分配器类型, m
是分配器, p
是类型 T *
和 v
是类型 T
。
正如您在20.6.8.2:5中发现的那样,这对于一般情况下的数组类型是无效的,因为它等同于调用
::new(static_cast<void *>(p))block(v);
这对于数组类型无效(数组不能通过括号初始化)。
实际上,你是正确的,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
}
另一个错误在于标准本身; 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
。
我遇到类似的问题后发现了这个讨论,resize()不适用于default-constructible类型。似乎gcc向量实现是不正确的。
仅供参考,我提交了一个针对gcc的错误:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64147