Я думаю, что порядок событий
- Компилятор не ищет функцию принимая
char[10]
собственно потому, что язык не поддерживает передачу массивов в качестве значений.
- Компилятор ищет функцию, ссылающуюся на ссылку на
char[10]
(и не находит).
- Компилятор ищет функцию с указателем на
char
, который является фактическим типом аргумента после так называемого типа настройки и не находит.
Последний пункт интересен тем, что функция шаблон f
фактически действительно принимает указатель на символ, как пояснялось другие плакаты: индекс в декларации является излишним, и в объявлении функции f(char p[])
p
не типа массив, но указатель типа на char. Обратите внимание, что это отличается от деклараций такого рода в другом месте (а не как параметр функции), где p
будет массивом, хотя и неполным.
Причина, по которой компилятор не может создать экземпляр шаблона функции, заключается не в том, что его аргумент неправильный: он будет соответствовать настройке типа аргумента. Причина в том, что не может вывести параметр шаблона N
из аргумента. В конце концов, для каждого N
был бы другой f
: какой должен компилятор взять ?? После того, как фактический аргумент buf
был «скорректирован» на указатель на его первый элемент, информация о длине в аргументе теряется. (Да, компиляторы глупы.)
Информация о длине сохранялась, когда вы объявили функцию ссылкой на массив.
Другая возможность состоит в том, чтобы просто создать экземпляр шаблона функции в явном виде:
f<10>(buf);
работы.
Первая строка такая же, как 'template void f (char *) {}' after * adjustment *, а затем нет способа вывести 'N' из вызова. Никакая настройка не применяется к 'char (&) [N]', поэтому можно вывести 'N'. –
@ M.M Точно. В тех случаях, когда параметр шаблона не может быть выведен, включая этот, он всегда может явно предоставить его. Ср Мой ответ. –
Почему бы не использовать std :: array в качестве аргумента? –