Warum ist std::array::size constexpr mit einfachen Typen (int, double, ...) aber nicht std::vector (GCC)?

Warum ist std::array::size constexpr mit einfachen Typen (int, double, ...) aber nicht std::vector (GCC)?


Der folgende Code:


std::array<int, 4> arr1;
std::array<float, arr1.size()> arr2;

...kompiliert mit beiden gcc und clang weil std::array::size gilt als constexpr .


Aber das Folgende kompiliert nicht mit gcc (Version 5.3.0 20151204):


std::array<std::vector<int>, 4> arr1;
std::array<std::vector<double>, arr1.size()> arr2;

Für mich gibt es keinen Grund, warum ein solcher Code nicht kompiliert werden sollte, wenn der erste funktioniert, aber da ich nicht viele Beiträge dazu gefunden habe, weiß ich nicht, ob es sich um einen gcc handelt Fehler oder ein clang Erweiterung?


Der Fehler von gcc (was ich nicht ganz verstehe... ):


main.cpp: In function 'int main()':
main.cpp:6:46: error: call to non-constexpr function 'constexpr std::array<_Tp, _Nm>::size_type std::array<_Tp, _Nm>::size() const [with _Tp = std::vector<int>; long unsigned int _Nm = 4ul; std::array<_Tp, _Nm>::size_type = long unsigned int]'
std::array<std::vector<double>, arr1.size()> arr2;
^
In file included from main.cpp:1:0:
/usr/local/include/c++/5.3.0/array:170:7: note: 'constexpr std::array<_Tp, _Nm>::size_type std::array<_Tp, _Nm>::size() const [with _Tp = std::vector<int>; long unsigned int _Nm = 4ul; std::array<_Tp, _Nm>::size_type = long unsigned int]' is not usable as a constexpr function because:
size() const noexcept { return _Nm; }
^
/usr/local/include/c++/5.3.0/array:170:7: error: enclosing class of constexpr non-static member function 'constexpr std::array<_Tp, _Nm>::size_type std::array<_Tp, _Nm>::size() const [with _Tp = std::vector<int>; long unsigned int _Nm = 4ul; std::array<_Tp, _Nm>::size_type = long unsigned int]' is not a literal type
/usr/local/include/c++/5.3.0/array:89:12: note: 'std::array<std::vector<int>, 4ul>' is not literal because:
struct array
^
/usr/local/include/c++/5.3.0/array:89:12: note: 'std::array<std::vector<int>, 4ul>' has a non-trivial destructor
main.cpp:6:46: error: call to non-constexpr function 'constexpr std::array<_Tp, _Nm>::size_type std::array<_Tp, _Nm>::size() const [with _Tp = std::vector<int>; long unsigned int _Nm = 4ul; std::array<_Tp, _Nm>::size_type = long unsigned int]'
std::array<std::vector<double>, arr1.size()> arr2;
^
main.cpp:6:48: note: in template argument for type 'long unsigned int'
std::array<std::vector<double>, arr1.size()> arr2;
^

Antworten:


Ich denke, dies hängt mit dem CWG-Problem 1684 zusammen. Zuvor war der constexpr enthaltene Anforderungen:



Und std::array<std::vector<int>, 4> ist nicht ein Literaltyp und daher sein size() Mitgliedsfunktion wäre nicht constexpr . Der neue Wortlaut lässt jedoch einen constexpr zu nicht statische Elementfunktionen für nicht literale Typen, vorausgesetzt, diese Funktionen erfüllen alle anderen Anforderungen von constexpr (welche array<T,N>::size() eindeutig tut).


Gemäß dem neuen Wortlaut ist dies ein gcc-Fehler. Zuvor abgelegt als 66297.


Einige Code-Antworten


std::array<int, 4>
arr1;
std::array<float, arr1.size()>
arr2;
std::array<std::vector<int>, 4>
arr1;
std::array<std::vector<double>, arr1.size()>
arr2;
main.cpp: In function 'int main()': main.cpp:6:46: error: call to non-constexpr function 'constexpr std::array<_Tp, _Nm>::size_type std::array<_Tp, _Nm>::size() const [with _Tp = std::vector<int>;
long unsigned int _Nm = 4ul;
std::array<_Tp, _Nm>::size_type = long unsigned int]'
std::array<std::vector<double>, arr1.size()>
arr2;
^ In file included from main.cpp:1:0: /usr/local/include/c++/5.3.0/array:170:7: note: 'constexpr std::array<_Tp, _Nm>::size_type std::array<_Tp, _Nm>::size() const [with _Tp = std::vector<int>;
long unsigned int _Nm = 4ul;
std::array<_Tp, _Nm>::size_type = long unsigned int]' is not usable as a constexpr function because:
size() const noexcept { return _Nm;
}
^ /usr/local/include/c++/5.3.0/array:170:7: error: enclosing class of constexpr non-static member function 'constexpr std::array<_Tp, _Nm>::size_type std::array<_Tp, _Nm>::size() const [with _Tp = std::vector<int>;
long unsigned int _Nm = 4ul;
std::array<_Tp, _Nm>::size_type = long unsigned int]' is not a literal type /usr/local/include/c++/5.3.0/array:89:12: note: 'std::array<std::vector<int>, 4ul>' is not literal because:
struct array ^ /usr/local/include/c++/5.3.0/array:89:12: note: 'std::array<std::vector<int>, 4ul>' has a non-trivial destructor main.cpp:6:46: error: call to non-constexpr function 'constexpr std::array<_Tp, _Nm>::size_type std::array<_Tp, _Nm>::size() const [with _Tp = std::vector<int>;
long unsigned int _Nm = 4ul;
std::array<_Tp, _Nm>::size_type = long unsigned int]'
std::array<std::vector<double>, arr1.size()>
arr2;
^ main.cpp:6:48: note: in template argument for type 'long unsigned int'
std::array<std::vector<double>, arr1.size()>
arr2;
^