Стандарт не совсем ясен в этом вопросе, и я думаю, что интерпретация GCC, вероятно, будет такой, как задумал WG21, но я не уверен.
Соответствующим разделом стандарта является [dcl.array], который описывает, как определить тип, объявленный объявлением, в котором декларатор содержит оператор формирования массива []
. Я цитирую соответствующую часть:
Граница массива также может быть опущена, когда за декларатором следует инициализатор (11.6) или когда за декларатором статического члена данных следует фигурная скобка или равный инициализатор (12,2). В обоих случаях граница рассчитывается из числа предоставленных начальных элементов (скажем, N
) (11.6.1), а тип идентификатора D
является «массивом N
T
».
Не совсем так, относится ли это только к объявлению самого массива, или же оно должно применяться в случае ссылки на массив, поскольку при интерпретации [dcl.ref] необходимо обращаться к [dcl.array] ] (который описывает операторы &
и &&
). Тем не менее, я думаю, что последняя интерпретация должна быть отклонена, так как мы не ожидаем, что инициализатор приведет к выводу границы, когда []
скрыт в деклараторе. Для примера рассмотрим надуманный пример:
int (*a[1])(const int (&)[]) = {0};
Здесь GCC и Clang согласны , и я думаю, что здравый смысл также согласен с тем, что тип a
равен int (*[1])(const int (&)[])
, а не int (*[1])(const int (&)[1])
: тот факт, что a
обладает инициализатором не вызывает вывод внутренней привязки массива.
Исходя из этого, я бы сказал, что GCC правильно не выводит массив, связанный с вашим кодом, так что a
имеет тип const int (&)[]
.