Ответ 1
Небольшая заметка, хотя и очень редко, я нашел несколько случаев, когда я считают, что компилятор Комоу ошибается, хотя эти случаи настолько редки, что их всегда стоит двойной и тройной проверяя ваши предположения!
У меня может быть причина для поведения 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++ допустимо выбрать первую перегрузку основанный на том, как он обрабатывает параметры разлагающегося массива, а Комо ошибается не иметь дедуктивного отказа для массива функций.
Конечно, теперь это означает, что (если бы Комо был исправлен), то каждый компилятор выбрали бы другую перегрузку и все равно были бы стандартами совместимый!: (
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?
Я хочу сказать, что стандарт ничего не говорит об этом. Я также хотел бы сказать, что любые формулировки по этому вопросу должны были бы оставить это как "undefined" или "поведение, определенное реализацией".