Аргументы шаблона могут быть указаны при ссылке на специализацию шаблона функции путем уточнения имени шаблона функции списком template-arguments таким же образом, как template-arguments это указывается при использовании специализации шаблона класса. [ Example:
template<class T> void sort(Array<T>& v); void f(Array<dcomplex>& cv, Array<int>& ci) { sort<dcomplex>(cv); // sort(Array<dcomplex>&) sort<int>(ci); // sort(Array<int>&) }
а также
template<class U, class V> U convert(V v); void g(double d) { int i = convert<int,double>(d); // int convert(double) char c = convert<char,double>(d); // char convert(double) }
— end example ]
Список аргументов шаблона может быть указан при ссылке на специализацию шаблона функции.
когда функция вызывается,
когда берется адрес функции, когда функция инициализирует ссылку на функцию или когда формируется указатель на функцию-член,
в явной специализации,
в явном экземпляре, или
в объявлении друга.
Конечные аргументы шаблона, которые могут быть deduced или получены по умолчанию, template-arguments могут быть исключены из списка явных template-arguments. Завершающий, template parameter pack не выведенный иным образом, будет выведен в пустую последовательность аргументов шаблона. Если все аргументы шаблона могут быть выведены, все они могут быть опущены; в этом случае сам пустой список аргументов шаблона <> также может быть опущен. В контекстах, где дедукция выполняется и терпит неудачу, или в контекстах, где дедукция не выполняется, если указан список аргументов шаблона и он, вместе с любыми аргументами шаблона по умолчанию, идентифицирует одну специализацию шаблона функции, тогда template-id это lvalue для функции специализация шаблона. [ Example:
template<class X, class Y> X f(Y); template<class X, class Y, class ... Z> X g(Y); void h() { int i = f<int>(5.6); // Y is deduced to be double int j = f(5.6); // ill-formed: X cannot be deduced f<void>(f<int, bool>); // Y for outer f deduced to be int (*)(bool) f<void>(f<int>); // ill-formed: f<int> does not denote a single function template specialization int k = g<int>(5.6); // Y is deduced to be double, Z is deduced to an empty sequence f<void>(g<int, bool>); // Y for outer f is deduced to be int (*)(bool), // Z is deduced to an empty sequence }
— end example ]
[ Note: Пустой список аргументов шаблона может использоваться, чтобы указать, что данное использование относится к специализации шаблона функции, даже если[dcl.fct]видна не являющаяся шаблоном функция ( ), которая в противном случае использовалась бы. Например:
template <class T> int f(T); // #1 int f(int); // #2 int k = f(1); // uses #2 int l = f<>(1); // uses #1
— end note ]
Присутствующие аргументы шаблона должны быть указаны в порядке объявления их соответствующих template-parameters. Список аргументов шаблона не должен указывать больше, template-arguments чем есть соответствующие, template-parameters если один из них не template-parameters является пакетом параметров шаблона. [ Example:
template<class X, class Y, class Z> X f(Y,Z); template<class ... Args> void f2(); void g() { f<int,const char*,double>("aa",3.0); f<int,const char*>("aa",3.0); // Z is deduced to be double f<int>("aa",3.0); // Y is deduced to be const char*, and Z is deduced to be double f("aa",3.0); // error: X cannot be deduced f2<char, short, int, long>(); // OK }
— end example ]
Неявные преобразования (Clause [conv]) будут выполнены для аргумента функции, чтобы преобразовать его в тип соответствующего параметра функции, если тип параметра не содержит никаких, template-parameters которые участвуют в выводе аргумента шаблона. [ Note: Параметры шаблона не участвуют в выводе аргументов шаблона, если они явно указаны. Например,
template<class T> void f(T);
class Complex {
Complex(double);
};
void g() {
f<Complex>(1); // OK, means f<Complex>(Complex(1))
}
— end note ]
[ Note: Поскольку явный список аргументов шаблона следует за именем шаблона функции и поскольку шаблоны функций-членов преобразования и шаблоны функций-членов конструктора вызываются без использования имени функции, невозможно предоставить явный список аргументов шаблона для этих шаблонов функций. ] — end note
[ Note: Для простых имен функций argument dependent lookup применяется, даже если имя функции не отображается в рамках вызова. Это потому, что вызов по-прежнему имеет синтаксическую форму вызова функции ([basic.lookup.unqual]). Но когда используется шаблон функции с явными аргументами шаблона, вызов не имеет правильной синтаксической формы, если не существует шаблона функции с таким именем, видимого в точке вызова. Если такое имя не отображается, вызов не имеет синтаксической правильной формы и поиск, зависящий от аргументов, не применяется. Если такое имя видно, применяется поиск, зависящий от аргументов, и дополнительные шаблоны функций могут быть найдены в других пространствах имен. [ Example:
namespace A { struct B { }; template<int X> void f(B); } namespace C { template<class T> void f(T t); } void g(A::B b) { f<3>(b); // ill-formed: not a function call A::f<3>(b); // well-formed C::f<3>(b); // ill-formed; argument dependent lookup applies only to unqualified names using C::f; f<3>(b); // well-formed because C::f is visible; then A::f is found by argument dependent lookup }
— end example ] ] — end note
Вывод аргументов шаблона может расширить последовательность аргументов шаблона, соответствующую пакету параметров шаблона, даже если последовательность содержит явно указанные аргументы шаблона. [ Example:
template<class ... Types> void f(Types ... values);
void g() {
f<int*, float*>(0, 0, 0); // Types is deduced to the sequence int*, float*, int
}
— end example ]