Почему 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 1684. Ранее требования constexpr
включали:
Класс, членом которого является функция constexpr
, является литеральный тип
И std::array<std::vector<int>, 4>
не является литеральным типом, и, следовательно, его функция-член size()
не будет constexpr
. Однако новая формулировка допускает нестатические функции-члены constexpr
для нелитеральных типов, предполагая, что эти функции отвечают всем другим требованиям constexpr
(что ясно показывает array<T,N>::size()
).
В новой редакции это ошибка gcc. Ранее было зарегистрировано как 66297.