Почему std::array::size constexpr с простыми типами (int, double,...), но не std:: vector (GCC)?

следующий код:

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

...компилируется с обоими gcc и clang, потому что std::array::size является constexpr.

но следующее не компилируется с gcc (версия 5.3.0 20151204):

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

для меня нет причин, по которым такой код не должен компилироваться, если первый работает, но поскольку я не нашел много сообщений об этом, я не знаю, является ли это 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;
                                                ^

1 ответов


Я думаю, что это связано с CWG issue 1684. Ранее в constexpr требования входят:

класс которого a constexpr функция является членом должна быть литерального типа

и std::array<std::vector<int>, 4> и не литеральный тип, и, следовательно, его size() функция-член не будет constexpr. Однако новая формулировка допускает constexpr нестатические функции-члены для небуквальные типов, предполагая, что эти функции отвечают все остальные требования constexpr (где array<T,N>::size() четко делает).

в новой формулировке это ошибка gcc. Ранее подано как 66297.