Ваш первый вопрос
если я вызову эту функцию шаблона
draw () в главном таким образом: draw (); является
это разрешено?
Как вы уже поняли, компилятор не может сам вывести , что вы имеете в виду draw<PNG>
, если нет аргументов функции, из которых можно это выяснить.
Итак, вы должны написать (как вы уже делаете):
int main() {
draw<PNG>();
}
Вы не можете опустить параметр шаблона здесь.
Ваш второй вопрос
и как шаблонная функция draw ()
знает, что PNG класс, и как
функция-член класса draw ()
называется?
Когда шаблон функции (A) создается с параметром PNG
, результирующее тело функции выглядит как (B):
// A:
template <typename Image>
void draw() {
Image::draw();
}
// B:
PNG::draw();
Анализатор знает, что для этого PNG
должно быть пространством имен или классом / структурой. Если это не так, функция не будет компилироваться.
Скажем, вы набрали draw<int>()
, например, вместо этого ваш код попытается вызвать int::draw()
, что невозможно.
Теперь, благодаря SFINAE (посмотрите!), Вы не получите ошибку компиляции для прерванного вызова int::draw()
; этот конкретный экземпляр будет просто запрещено существовать. Вероятно, вам скажут, что «функция не соответствует draw()
», так как & mdash; дисконтирование запрещенных экземпляров & mdash; нет никакой возможной перегрузки функции draw
, которую она может выбрать для использования.