gcc.gnu.org/bugzilla/show_bug.cgi?id=38950
омпилятор ведет себя странно, когда я пытаюсь передать массив фиксированного размера в функцию шаблона. Код выглядит следующим образом:
#include <algorithm>
#include <iostream>
#include <iterator>
template <typename TSize, TSize N>
void f(TSize (& array)[N]) {
std::copy(array, array + N, std::ostream_iterator<TSize>(std::cout, " "));
std::cout << std::endl;
}
int main() {
int x[] = { 1, 2, 3, 4, 5 };
unsigned int y[] = { 1, 2, 3, 4, 5 };
f(x);
f(y); //line 15 (see the error message)
}
В GCC 4.1.2 выдается следующая ошибка компиляции:
test.cpp|15| error: size of array has non-integral type ‘TSize’
test.cpp|15| error: invalid initialization of reference of type
‘unsigned int (&)[1]’ from expression of type ‘unsigned int [5]’
test.cpp|6| error: in passing argument 1 of ‘void f(TSize (&)[N])
[with TSize = unsigned int, TSize N = ((TSize)5)]’
Обратите внимание, что первый вызов компилируется и завершается успешно. Это, кажется, подразумевает, что в то время какint
является интегральным,unsigned int
нет.
Однако, если я изменю объявление моего вышеупомянутого шаблона функции на
template <typename TSize, unsigned int N>
void f(TSize (& array)[N])
проблема просто уходит! Обратите внимание, что единственное изменение здесьTSize N
вunsigned int N
.
Раздел [dcl.type.simple
] в окончательном проекте ISO / IEC FDIS 14882: 1998, по-видимому, подразумевается, что «интегральный тип» либо подписан, либо не подписан:
signed
Спецификатор силыchar
объекты и битовые поля для подписи; это избыточно с другими интегральными типами.
Что касается объявлений массивов фиксированного размера, в проекте говорится [dcl.array
]:
Есликонстанта-выражение (expr.const
) присутствует, оно должно быть интегральным постоянным выражением, и его значение должно быть больше нуля.
Так почему мой код работает с явнымunsigned
тип размера, с выводомsigned
тип размера, но не с выводомunsigned
тип размера?
РЕДАКТИРОВАТЬ Серж хочет знать, где мне нужна первая версия. Во-первых, этот пример кода явно упрощен. Мой настоящий код немного сложнее. Массив на самом деле является массивом индексов / смещений в другом массиве.Таким образом, по логике, тип массива должен быть таким же, как его тип размера для максимальной корректности. В противном случае я могу получить несоответствие типов (например, междуunsigned int
а такжеstd::size_t
). По общему признанию, это не должно быть проблемой на практике, так как компилятор неявно преобразует в больший из двух типов.
РЕДАКТИРОВАТЬ 2 Я исправлен (спасибо, горит): размер и смещение, конечно, логически разные типы, и смещения в C-массивах, в частности, имеют типstd::ptrdiff_t
.