为什么 std::array::size constexpr 具有简单类型(int、double、...)而不是 std::vector (GCC)?

Why is std::array::size constexpr with simple types (int, double, ...) but not std::vector (GCC)?

以下代码:

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

...用 gccclang 编译,因为 std::array::size 被认为是 constexpr.

但以下不编译 gcc(版本 5.3.0 20151204):

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

对我来说,如果第一个有效,这样的代码没有理由编译失败,但由于我没有找到很多 post,所以我不知道它是否是 gcc 错误或 clang 扩展?

来自 gcc 的错误(我不太明白...):

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;
                                                ^

我认为这与 CWG issue 1684 有关。以前,constexpr 要求包括:

The class of which a constexpr function is a member shall be a literal type

std::array<std::vector<int>, 4>不是文字类型,因此它的size()成员函数不会是constexpr。但是,新的措辞允许 constexpr 非文字类型的非静态成员函数,假设这些函数满足 constexpr 的所有其他要求(array<T,N>::size() 显然满足)。

根据新的措辞,这是一个 gcc 错误。以前归档为 66297.