Небольшая заметка, хотя и очень редкая, я нашел несколько случаев, когда я
считаю, что компилятор Comeau ошибается - хотя, эти
случаи настолько редки, что всегда стоит двойной и тройной
проверка ваших предположений!
У меня может быть причина для поведения g ++. Я не уверен, что это
указывается точно при настройке типов параметров:
Рассмотрим следующее:
template<typename T>
struct A
{
void bar (T[10]);
};
template<typename T>
void A<T>::bar (T*)
{
}
Определение 'bar' допустимо, так как "T [10]" распадается на "T *". я делаю
не вижу ничего в стандарте, который запрещает компилятору
выполнение корректировок 8.3.5 по отношению к объявлению шаблона,
и это также улучшает производительность, когда дело доходит до согласования перегрузки.
Применяя это к вашему примеру, g ++ может трактовать это как:
template<typename T>
char (&f( T* ))[1];
template<typename T>
char (&f(...))[2];
int main() { char c[sizeof(f<void()>(0)) == 2]; }
В приведенном выше примере замещенный параметр является допустимым указателем на
функция, а не массив функций.
Итак, вопрос для меня - есть ли что-то, что запрещает
корректировки для параметров функции (8.3.5) дважды?
Лично я думаю, что имеет смысл позволить корректировкам произойти
дважды, так как в противном случае это усложняет сопоставление шаблона функции
Перегрузки
В заключение, я считаю правильным для g ++ выбрать первую перегрузку
основанный на том, как он обрабатывает затухающие параметры массива, и Comeau не так
не иметь ошибки вывода для массива функций.
Конечно, теперь это означает, что (если Comeau был исправлен), то каждый компилятор
выбрал бы другую перегрузку и все равно был бы стандартами
совместимый! (
EDIT:
Просто чтобы проиллюстрировать мою точку зрения, рассмотрим следующий код:
template <typename T> void foo ( T * );
template <typename T> void foo ( T * const );
template <typename T> void foo ( T [] );
template <typename T> void foo ( T [10] );
template <typename T> void foo ( T [100] );
void bar ()
{
foo < void() > ( 0 );
}
Здесь foo объявляется и повторно объявляется несколько раз. Какое объявление и, следовательно, какой тип параметра должен компилятор применять правила, перечисленные в 14.8.2?
Я хочу сказать, что стандарт ничего не говорит о вышеизложенном. Я также хотел бы сказать, что любая формулировка по этому вопросу должна оставлять ее как «неопределенное» или «определяемое реализацией» поведение.