Получение количества элементов в std:: array во время компиляции
Является ли следующий код С++ действительным и почему?
std::array<std::string, 42> a1;
std::array<int, a1.size()> a2;
Он не компилируется в GCC 4.8 (в режиме С++ 11). Существует простое, но неэлегантное решение:
std::array<std::string, 42> a1;
std::array<int, sizeof(a1)/sizeof(a1[0])> a2;
Так ясно, что компилятор может определить количество элементов в std:: array. Почему std:: array:: size() не является функцией constexpr static
?
EDIT:
Я нашел другое обходное решение:
std::array<std::string, 42> a1;
std::array<int, std::tuple_size<decltype(a1)>::value> a2;
Ответы
Ответ 1
array<T>::size()
constexpr
, но вы не можете использовать его таким образом, потому что a1
не является значением constexpr
. Кроме того, он не может быть constexpr
, потому что string
не является литеральным типом.
Однако вы можете обойти это, если хотите, путем вывода параметра шаблона size_t
. Пример:
#include <string>
#include <array>
#include <iostream>
using namespace std;
template<typename>
struct array_size;
template<typename T, size_t N>
struct array_size<array<T,N> > {
static size_t const size = N;
};
array<string, 42> a1;
array<string, array_size<decltype(a1)>::size> a2;
int main() {
cout << a2.size() << endl;
}
Ответ 2
std::array::size
на самом деле требуется constexpr
в соответствии с § 23.3.2.1 стандарта С++ 11:
23.3.2.4 array::size [array.size]
template <class T, size_t N> constexpr size_type array<T,N>::size() noexcept;
Returns: N
Я предполагаю, что это просто проскользнуло мимо того, кто его реализовал в GCC.
После тестирования это работает:
std::array<int, 42> a1;
std::array<int, a1.size()> a2;
Это может иметь какое-то отношение к std::string
, не являющемуся допустимым типом constexpr
, чтобы делать экземпляры времени компиляции, тогда как int
есть.
Ответ 3
Вы можете использовать тот же метод вывода шаблона, который всегда использовался для обнаружения привязки массива С++ 98.
template<size_t N, typename T>
constant_integer<N> array_size( const std::array<T, N>& );
Сделайте приятную обертку макросов и наслаждайтесь!
Возможны также многие варианты, такие как:
Ответ 4
Это не статично, но это constexpr
http://www.cplusplus.com/reference/array/array/size/
EDIT: это может быть не ошибка, посмотрите на Ошибка, используя constexpr в качестве параметра шаблона в пределах того же класса