应该(在C ++ 11)std :: vector :: resize(size_type)工作为默认可构造的value_type int [4]? [英] Should (in C++11) std::vector::resize(size_type) work for the default constructible value_type int[4]?
问题描述
在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>一个;
static_assert(is_default_constructible< block> :: value,;--(); //不会触发
A.resize(100); //编译器错误
那么我的理解是错误的还是gcc是错误的。
解决方案
vector.resize(n)
上的要求(23.3.6.3:10)是正确的,T
应为CopyInsertable
,即以下内容应格式良好(23.2.1:13) p>
allocator_traits< A> :: construct(m,p,v);
pre>
其中
A
是向量的分配器类型,m
是分配器,p
的类型为T *
和v
是T
类型。
正如你可以从20.6.8.2:5发现,对于一般情况下的数组类型无效,因为它等效于调用
:: new(static_cast< void *> ))块(v);
对数组类型无效(数组不能用括号初始化)。
其实,你是正确的g ++有一个错误;应该总是可以通过提供一个合适的分配器来解决
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:: new(static_cast< void *>(p + i))T {v [i]};
}
};
int main(){
std :: vector< int [4],ArrayAllocator< int,4> C;
c.resize(100); // failed
typedef ArrayAllocator< int,4>一个;
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 :: declval< Args>()...)
,它对数组类型有效(如@Johannes Schaub-litb指出,数组类型可以用< >(零包扩展) )。然而,除了T()
的形式良好,17.6.3.1:2需要DefaultConstructible
数组类型T
的情况,但未由std :: is_default_constructible
检查。In C++11, there are two versions of
std::vector::resize()
:void resize( size_type count ); void resize( size_type count, const value_type& value);
I understand (as suggested by one of the comments to one of the answers to this question) that the first requires
value_type
to be default constructible, while the second requires it to be copy constructible. However, (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
So either my understanding was wrong or gcc is buggy. Which?
解决方案The requirement (23.3.6.3:10) on
vector.resize(n)
being well-formed is thatT
should beCopyInsertable
, i.e. that the following should be well-formed (23.2.1:13):allocator_traits<A>::construct(m, p, v);
where
A
is the allocator type of the vector,m
is the allocator,p
is of typeT *
andv
is of typeT
.As you can discover from 20.6.8.2:5, this is invalid for array types in the general case as it is equivalent to calling
::new(static_cast<void *>(p))block(v);
which is invalid for array types (arrays cannot be initialized by parentheses).
Actually, you're correct that g++ has a bug; it should always be possible to work around the issue with
CopyInsertable
by providing an appropriate allocator, but g++ fails to allow this:#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 }
Another bug is in the standard itself; 20.9.4.3:3 specifies
std::is_default_constructible<T>
as equivalent tostd::is_constructible<T>
, where 20.9.4.3:6 specifiesstd::is_constructible<T, Args...>
as the well-formedness criterion onT t(std::declval<Args>()...)
, which is valid for array types (as @Johannes Schaub-litb points out, array types can be initialised with(zero-pack-expansion)
). However, 17.6.3.1:2 requires forDefaultConstructible
in addition thatT()
be well-formed, which is not the case for an array typeT
but is not checked bystd::is_default_constructible
.这篇关于应该(在C ++ 11)std :: vector :: resize(size_type)工作为默认可构造的value_type int [4]?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!