Подтвердить что ты не робот

Получение количества элементов в 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;
4b9b3361

Ответ 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>& );

Сделайте приятную обертку макросов и наслаждайтесь!

Возможны также многие варианты, такие как: