Стандарт C++ 11 (1119564), страница 96
Текст из файла (страница 96)
The new parameter is of type “reference to cv A,” where cvare the cv-qualifiers of the function template (if any) and A is the class of which the function template is amember. [ Note: This allows a non-static member to be ordered with respect to a nonmember function andfor the results to be equivalent to the ordering of two equivalent nonmembers. — end note ] [ Example:struct A { };template<class T> struct B {template<class R> int operator*(R&);};template<class T, class R> int operator*(T&, R&);// #1// #2// The declaration of B::operator* is transformed into the equivalent of// template<class R> int operator*(B<A>&, R&);// #1aint main() {A a;B<A> b;§ 14.5.6.2© ISO/IEC 2011 – All rights reserved349ISO/IEC 14882:2011(E)// calls #1ab * a;}— end example ]4Using the transformed function template’s function type, perform type deduction against the other templateas described in 14.8.2.4.[ Example:template<class T> struct A { A(); };template<class T> void f(T);template<class T> void f(T*);template<class T> void f(const T*);template<class T> void g(T);template<class T> void g(T&);template<class T> void h(const T&);template<class T> void h(A<T>&);void m() {const int *p;f(p);float x;g(x);A<int> z;h(z);const A<int> z2;h(z2);}// f(const T*) is more specialized than f(T) or f(T*)// Ambiguous: g(T) or g(T&)// overload resolution selects h(A<T>&)// h(const T&) is called because h(A<T>&) is not callable— end example ]5[ Note: Since partial ordering in a call context considers only parameters for which there are explicit call arguments, some parameters are ignored (namely, function parameter packs, parameters with default arguments,and ellipsis parameters).
[ Example:template<classtemplate<classtemplate<classtemplate<classint main() {int* ip;f(ip);g(ip);}T>T>T>T>voidvoidvoidvoidf(T);f(T*, int=1);g(T);g(T*, ...);////////#1#2#3#4// calls #2// calls #4— end example ] [ Example:template<class T, class U> struct A { };template<class T, class U> void f(U, A<U, T>* p = 0); // #1template<class U> void f(U, A<U, U>* p = 0); // #2template<class T> void g(T, T = T());// #3§ 14.5.6.2350© ISO/IEC 2011 – All rights reservedISO/IEC 14882:2011(E)template<class T, class...
U> void g(T, U ...);// #4void h() {f<int>(42, (A<int, int>*)0);f<int>(42);g(42);}// calls #2// error: ambiguous// error: ambiguous— end example ] [ Example:template<classtemplate<classtemplate<classtemplate<classT, class... U> voidT> voidT, class... U> voidT> voidf(T, U...);f(T);g(T*, U...);g(T);void h(int i) {f(&i);g(&i);}////////#1#2#3#4// error: ambiguous// OK: calls #3— end example ] — end note ]14.5.7Alias templates[temp.alias]1A template-declaration in which the declaration is an alias-declaration (Clause 7) declares the identifier tobe a alias template.
An alias template is a name for a family of types. The name of the alias template is atemplate-name.2When a template-id refers to the specialization of an alias template, it is equivalent to the associated typeobtained by substitution of its template-arguments for the template-parameters in the type-id of the aliastemplate. [ Note: An alias template name is never deduced. — end note ] [ Example:template<class T> struct Alloc { /∗ ... ∗/ };template<class T> using Vec = vector<T, Alloc<T>>;Vec<int> v;// same as vector<int, Alloc<int>> v;template<class T>void process(Vec<T>& v){ /∗ ...
∗/ }template<class T>void process(vector<T, Alloc<T>>& w){ /∗ ... ∗/ }// error: redefinitiontemplate<template<class> class TT>void f(TT<int>);f(v);// error: Vec not deducedtemplate<template<class,class> class TT>void g(TT<int, Alloc<int>>);g(v);// OK: TT = vector— end example ]§ 14.5.7© ISO/IEC 2011 – All rights reserved351ISO/IEC 14882:2011(E)3The type-id in an alias template declaration shall not refer to the alias template being declared. The typeproduced by an alias template specialization shall not directly or indirectly make use of that specialization.[ Example:template <class T> struct A;template <class T> using B = typename A<T>::U;template <class T> struct A {typedef B<T> U;};B<short> b;// error: instantiation of B<short> uses own type via A<short>::U— end example ]14.61Name resolution[temp.res]Three kinds of names can be used within a template definition:— The name of the template itself, and names declared within the template itself.— Names dependent on a template-parameter (14.6.2).— Names from scopes which are visible within the template definition.2A name used in a template declaration or definition and that is dependent on a template-parameter isassumed not to name a type unless the applicable name lookup finds a type name or the name is qualifiedby the keyword typename.
[ Example:// no B declared hereclass X;template<class T> class Y {class Z;void f() {X* a1;T* a2;Y* a3;Z* a4;typedef typename T::A TA;TA* a5;typename T::A* a6;T::A* a7;B* a8;// forward declaration of member class////////declaredeclaredeclaredeclarepointerpointerpointerpointertotototo////////////////declare pointer to T’s Adeclare pointer to T’s AT::A is not a type name:multiply T::A by a7; ill-formed,no visible declaration of a7B is not a type name:multiply B by a8; ill-formed,no visible declarations of B and a8XTY<T>Z}};— end example ]3When a qualified-id is intended to refer to a type that is not a member of the current instantiation (14.6.2.1)and its nested-name-specifier refers to a dependent type, it shall be prefixed by the keyword typename, forminga typename-specifier.
If the qualified-id in a typename-specifier does not denote a type, the program is illformed.§ 14.6352© ISO/IEC 2011 – All rights reservedISO/IEC 14882:2011(E)typename-specifier:typename nested-name-specifier identifiertypename nested-name-specifier templateopt simple-template-id4If a specialization of a template is instantiated for a set of template-arguments such that the qualified-idprefixed by typename does not denote a type, the specialization is ill-formed.
The usual qualified namelookup (3.4.3) is used to find the qualified-id even in the presence of typename. [ Example:struct A {struct X { };int X;};struct B {struct X { };};template<class T> void f(T t) {typename T::X x;}void foo() {A a;B b;f(b);// OK: T::X refers to B::Xf(a);// error: T::X refers to the data member A::X not the struct A::X}— end example ]5A qualified name used as the name in a mem-initializer-id, a base-specifier, or an elaborated-type-specifieris implicitly assumed to name a type, without the use of the typename keyword. In a nested-name-specifierthat immediately contains a nested-name-specifier that depends on a template parameter, the identifier orsimple-template-id is implicitly assumed to name a type, without the use of the typename keyword.
[ Note:The typename keyword is not permitted by the syntax of these constructs. — end note ]6If, for a given set of template arguments, a specialization of a template is instantiated that refers to aqualified-id that denotes a type, and the qualified-id refers to a member of an unknown specialization, thequalified-id shall either be prefixed by typename or shall be used in a context in which it implicitly names atype as described above. [ Example:template <class T> void f(int i) {T::x * i;// T::x must not be a type}struct Foo {typedef int x;};struct Bar {static int const x = 5;};int main() {f<Bar>(1);f<Foo>(1);}// OK// error: Foo::x is a type— end example ]§ 14.6© ISO/IEC 2011 – All rights reserved353ISO/IEC 14882:2011(E)7Within the definition of a class template or within the definition of a member of a class template followingthe declarator-id, the keyword typename is not required when referring to the name of a previously declaredmember of the class template that declares a type.
[ Note: such names can be found using unqualified namelookup (3.4.1), class member lookup (3.4.3.1) into the current instantiation (14.6.2.1), or class member accessexpression lookup (3.4.5) when the type of the object expression is the current instantiation (14.6.2.2). — endnote ] [ Example:template<class T> struct A {typedef int B;B b;// OK, no typename required};— end example ]8Knowing which names are type names allows the syntax of every template definition to be checked. Nodiagnostic shall be issued for a template definition for which a valid specialization can be generated. If novalid specialization can be generated for a template definition, and that template is not instantiated, thetemplate definition is ill-formed, no diagnostic required.
If every valid specialization of a variadic templaterequires an empty template parameter pack, the template definition is ill-formed, no diagnostic required.If a type used in a non-dependent name is incomplete at the point at which a template is defined but iscomplete at the point at which an instantiation is done, and if the completeness of that type affects whetheror not the program is well-formed or affects the semantics of the program, the program is ill-formed; nodiagnostic is required. [ Note: If a template is instantiated, errors will be diagnosed according to the otherrules in this Standard.
Exactly when these errors are diagnosed is a quality of implementation issue. — endnote ] [ Example:int j;template<class T> class X {void f(T t, int i, char* p) {t = i;// diagnosed if X::f is instantiated// and the assignment to t is an errorp = i;// may be diagnosed even if X::f is// not instantiatedp = j;// may be diagnosed even if X::f is// not instantiated}void g(T t) {+;// may be diagnosed even if X::g is// not instantiated}};template<class... T> struct A {void operator++(int, T... t);// error: too many parameters};template<class... T> union X : T... { };// error: union with base classtemplate<class... T> struct A : T..., T...
{ };// error: duplicate base class— end example ]9When looking for the declaration of a name used in a template definition, the usual lookup rules (3.4.1,3.4.2) are used for non-dependent names. The lookup of names dependent on the template parameters ispostponed until the actual template argument is known (14.6.2). [ Example:#include <iostream>using namespace std;§ 14.6354© ISO/IEC 2011 – All rights reservedISO/IEC 14882:2011(E)template<class T> class Set {T* p;int cnt;public:Set();Set<T>(const Set<T>&);void printall() {for (int i = 0; i<cnt; i++)cout << p[i] << ’\n’;}};in the example, i is the local variable i declared in printall, cnt is the member cnt declared in Set, andcout is the standard output stream declared in iostream.
However, not every declaration can be found thisway; the resolution of some names must be postponed until the actual template-arguments are known. Forexample, even though the name operator<< is known within the definition of printall() and a declarationof it can be found in <iostream>, the actual declaration of operator<< needed to print p[i] cannot beknown until it is known what type T is (14.6.2).