«Неявно» - правильный ответ. Шаблоны эффективно создают сценарий «типизирования утки» благодаря способу их компиляции. Вы можете вызывать любые функции по значению типа шаблона, и единственные экземпляры, которые будут приняты, это те, для которых этот метод определен. Например:
template <class T>
int compute_length(T *value)
{
return value->length();
}
Мы можем вызвать этот метод для указателя на любой тип, который объявляет метод length()
для возврата int
. Thusly:
string s = "test";
vector<int> vec;
int i = 0;
compute_length(&s);
compute_length(&vec);
... но не указатель на тип, который не объявляет length()
:
compute_length(&i);
Этот третий пример не скомпилируется.
Это работает, потому что C ++ компилирует новую версию шаблонизированной функции (или класса) для каждого экземпляра. Выполняя эту компиляцию, он выполняет прямую, почти макроподобную подстановку экземпляра шаблона в код перед проверкой типа. Если все работает с этим шаблоном, компиляция продолжается, и мы в итоге получаем результат. Если что-то не получается (например, int*
не объявляет length()
), то мы получаем страшную ошибку во время компиляции шаблона из шести страниц.