Пожалуйста, рассмотрите этот код:
template<typename T>
char (&f(T[1]))[1];
template<typename T>
char (&f(...))[2];
int main() { char c[sizeof(f<void()>(0)) == 2]; }
Я ожидал, что он сделает SFINAE и переключит вторую перегрузку, так как подстановка T
в T[1]
дает
void [1]()
Конечно, это недопустимый тип. Настройка типов параметров (array- > pointer) выполняется после подстановки параметров шаблона в параметры функции и проверки допустимых результирующих типов, таких как 14.8.2 [temp.deduct].
Но оба comeau и GCC не могут скомпилировать выше. Оба с различной диагностикой.
Комо говорит:
"ComeauTest.c", строка 2: ошибка: массив функций не разрешен
char (&f(T[1]))[1];
GCC говорит (версия 4.3.3
):
ошибка: ISO С++ запрещает массив нулевого размера
c
Значение, GCC не подлежит замене, но он выбирает первую перегрузку f
, возвращая sizeof
из 1, вместо того, чтобы не подставлять ее спереди, как Comeau.
Какой компилятор прав, и мой код действительно вообще? Пожалуйста, обратитесь к соответствующему разделу "Стандарт" в вашем ответе. Спасибо!
Обновить. Сам стандарт содержит такой пример в списке в 14.8.2/2
. Я не знаю, почему я сначала его не заметил:
template <class T> int f(T[5]);
int I = f<int>(0);
int j = f<void>(0); // invalid array
Пока пример только информативен, он показывает намерение всех этих таинственных абзацев и, кажется, показывает, что код выше должен работать и отклонять первую перегрузку.