Они эквивалентны. В первом случае why
- это введенное имя, которое определено так же, как why<T>
(где T
- фактический аргумент шаблона.) Это существует для простоты ввода.
Обратите внимание, что эта инъекция находится в области видимости класса, а не вне его. Очевидно, но дано:
template <typename T>
struct foo
{
foo x(foo f);
};
Распространенной ошибкой может быть попытка определить x
следующим образом:
template <typename T>
foo foo<T>::x(foo f) { return f; }
Но это будет ошибкой, поскольку foo
в возвращаемом типе требует аргументов шаблона. Тем не менее, foo
в списке параметров в порядке, потому что после foo<T>::
мы находимся в области видимости класса, а foo
определено как foo<T>
. Таким образом, правильный способ сделать это один из следующих:
template <typename T>
foo<T> foo<T>::x(foo f) { return f; }
template <typename T>
foo<T> foo<T>::x(foo<T> f) { return f; } // equivalent