Vector of array fails to compile [duplicate]
Asked Answered
G

1

4

This simple program

#include <vector>

int main()
{
    using int3 = int[3];
    std::vector<int3> vec( 2 );
}

does not compile in the latest Visual Studio 2019 16.10.0 with stdcpplatest switch, producing the error:

>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30037\include\xutility(144,1): error C2440: 'return': cannot convert from 'int *' to '_Ty (*)'
1>        with
1>        [
1>            _Ty=int [3]
1>        ]
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30037\include\xutility(144,48): message : Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30037\include\xmemory(707): message : see reference to function template instantiation '_Ty (*std::construct_at<_Objty,,void>(_Ty (*const )) noexcept)[3]' being compiled
1>        with
1>        [
1>            _Ty=int [3],
1>            _Objty=int [3]
1>        ]
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30037\include\xmemory(1610): message : see reference to function template instantiation 'void std::_Default_allocator_traits<_Alloc>::construct<_Ty,>(_Alloc &,_Objty (*const ))' being compiled
1>        with
1>        [
1>            _Alloc=std::allocator<int3>,
1>            _Ty=int [3],
1>            _Objty=int [3]
1>        ]
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30037\include\xmemory(1611): message : see reference to function template instantiation 'void std::_Default_allocator_traits<_Alloc>::construct<_Ty,>(_Alloc &,_Objty (*const ))' being compiled
1>        with
1>        [
1>            _Alloc=std::allocator<int3>,
1>            _Ty=int [3],
1>            _Objty=int [3]
1>        ]
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30037\include\xmemory(1811): message : see reference to function template instantiation 'void std::_Uninitialized_backout_al<_Alloc>::_Emplace_back<>(void)' being compiled
1>        with
1>        [
1>            _Alloc=std::allocator<int3>
1>        ]
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30037\include\xmemory(1811): message : see reference to function template instantiation 'void std::_Uninitialized_backout_al<_Alloc>::_Emplace_back<>(void)' being compiled
1>        with
1>        [
1>            _Alloc=std::allocator<int3>
1>        ]
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30037\include\vector(1648): message : see reference to function template instantiation 'int (*std::_Uninitialized_value_construct_n<std::allocator<int3>>(int (*)[3],unsigned __int64,_Alloc &))[3]' being compiled
1>        with
1>        [
1>            _Alloc=std::allocator<int3>
1>        ]
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30037\include\vector(1646): message : while compiling class template member function 'int (*std::vector<int3,std::allocator<int3>>::_Ufill(int (*)[3],const unsigned __int64,std::_Value_init_tag))[3]'
1>C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30037\include\vector(493): message : see reference to function template instantiation 'int (*std::vector<int3,std::allocator<int3>>::_Ufill(int (*)[3],const unsigned __int64,std::_Value_init_tag))[3]' being compiled
1>Test.cpp(271): message : see reference to class template instantiation 'std::vector<int3,std::allocator<int3>>' being compiled
1>Done building project "Project1.vcxproj" -- FAILED.

The program compiled fine in the previous version of Visual Studio 2019 16.9.5, as well as in gcc 11, but fails to compile in clang 5 as well. Is std::vector of array permitted by the standard or is it an implementation specific behavior?

Gualtiero answered 28/5, 2021 at 8:2 Comment(2)
dupe of Correct way to work with vector of arraysCobblestone
Similar question: #75558951Gualtiero
E
5

From cppreference:

T - The type of the elements.

(until C++11)

T must meet the requirements of CopyAssignable and CopyConstructible.

(since C++11) (until C++17)

The requirements that are imposed on the elements depend on the actual operations performed on the container. Generally, it is required that element type is a complete type and meets the requirements of Erasable, but many member functions impose stricter requirements.

(since C++17)

The requirements that are imposed on the elements depend on the actual operations performed on the container. Generally, it is required that element type meets the requirements of Erasable, but many member functions impose stricter requirements. This container (but not its members) can be instantiated with an incomplete element type if the allocator satisfies the allocator completeness requirements.

C arrays are not CopyAssignable nor CopyConstructible. They are also not Erasable (see here), and even if they were, most methods require more than that.

You can create a vector of std::array<int,3> without problems.

PS: In principle it would be possible to write a custom allocator that allows you to construct a std::vector of c-arrays (see here and comments on that answer). Though, this is mainly a curiosity, because you would still be rather limited. The requirements have been lifted in C++11, but nevertheless "many member functions impose stricter requirements".

Euphony answered 28/5, 2021 at 8:18 Comment(1)
In C++20 the things have changed, please consult with this answer: https://mcmap.net/q/243660/-using-c-style-arrays-in-std-vector-msvc-bugGualtiero

© 2022 - 2024 — McMap. All rights reserved.