Скажем, у меня есть функция вроде:
int test(std::array<char, 8>* data) {
char buffer[data->size() * 2];
[... some code ...]
}
ясно, что размер буфера можно оценить во время компиляции: данные имеют размер constexpr
из 8 элементов, 8 * 2 = 16 байт.
Однако при компиляции с -Wall
, -pedantic
и -std=c++11
я получаю печально известную ошибку:
предупреждение: массивы переменной длины являются функцией C99 [-Wvla-extension]
что, я считаю, имеет смысл: array::size()
это constexpr
, но это все еще метод, и в приведенной выше функции мы все еще должны разыменовывать указатель, который не является constexpr
.
Если я попробую что-то вроде:
int test(std::array<char, 8>& data) {
char buffer[data.size() * 2];
[...]
}
gcc
(пробовал версию 5.2.0) вроде доволен: предупреждения нет.
Но с clang++
(3.5.1) я все равно получаю предупреждение о массивах переменной длины.
В моем случае я не могу легко изменить подпись test
, она должна принимать указатель. Итак... несколько вопросов:
Каков наилучший/самый стандартный способ получить размер
std::array
указателя в контексте constexpr?Ожидается ли разница в поведении указателей и ссылок? Какой компилятор прав в предупреждении,
gcc
илиclang
?
size
не является статической функцией-членом. - person dyp   schedule 06.10.2015template<typename T, std::size_t N> std::size_t arraysize(const std::array<T, N>& array) { return N; }
, который можно использовать выше. Тем не менее... это правильный путь? Кажется искаженным. - person rabexc   schedule 06.10.2015nullptr
; конечно, он не может сделать там ничего полезного, но это также означает, чтоsize
не определено должным образом. Если быsize
был виртуальным, я бы увидел, что он ругается как с указателями, так и со ссылками (потому что это может быть тип, производный отstd::array<char, 8>
, который не имеет такой же реализацииsize
), но здесь это явно не тот случай. - person ShadowRanger   schedule 06.10.2015std::array
? Вы могли бы исправить слишком общую жалобу, указавchar
и указав только размер. - person Ben Voigt   schedule 06.10.2015std::tuple_size<decltype(*arr)>::value
? - person tforgione   schedule 06.10.2015&*data
в случае указателя или&data
в случае ссылки и его преобразование из lvalue в rvalue и сообщают об ошибке, поскольку этот адрес не может быть постоянным выражением. Адрес используется для инициализации указателяthis
неявно через [expr.call]p4. - person dyp   schedule 06.10.2015remove_reference_t
, что делает его довольно длинным. - person dyp   schedule 06.10.2015constexpr auto s = data.size()
, поскольку это не является постоянным выражением. - person edmz   schedule 06.10.2015