Should (in C++11) std::vector::resize(size_type) work for the default constructible value_type int[4]?

后端 未结 2 1791
遇见更好的自我
遇见更好的自我 2021-01-17 13:34

In C++11, there are two versions of std::vector::resize():

void resize( size_type count );
void resize( size_type count, const value_type& v         


        
相关标签:
2条回答
  • 2021-01-17 14:04

    I found this discussion after I ran into a similar problem with resize() not working for a default-constructible type. It seems like the gcc vector implementation is incorrect.

    FYI, I filed a bug against gcc: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64147

    0 讨论(0)
  • 2021-01-17 14:10

    The requirement (23.3.6.3:10) on vector.resize(n) being well-formed is that T should be CopyInsertable, 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 type T * and v is of type T.

    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 to std::is_constructible<T>, where 20.9.4.3:6 specifies std::is_constructible<T, Args...> as the well-formedness criterion on T 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 for DefaultConstructible in addition that T() be well-formed, which is not the case for an array type T but is not checked by std::is_default_constructible.

    0 讨论(0)
提交回复
热议问题