Стандарт C++ 98 (1119566), страница 72
Текст из файла (страница 72)
Exactly when these errors are diagnosed is a quality ofimplementation issue. ] [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}};—end example]8When 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 nondependent 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;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,and cout is the standard output stream declared in iostream. However, not every declaration can be259ISO/IEC 14882:1998(E)© ISO/IEC14.6 Name resolution14 Templatesfound this way; the resolution of some names must be postponed until the actual template-arguments areknown.
For example, even though the name operator<< is known within the definition ofprintall() and a declaration of it can be found in <iostream>, the actual declaration ofoperator<< needed to print p[i] cannot be known until it is known what type T is (14.6.2). ]9If a name does not depend on a template-parameter (as defined in 14.6.2), a declaration (or set of declarations) for that name shall be in scope at the point where the name appears in the template definition; thename is bound to the declaration (or declarations) found at that point and this binding is not affected bydeclarations that are visible at the point of instantiation.
[Example:void f(char);template<class T> void g(T t){f(1);f(T(1));f(t);dd++;// f(char)// dependent// dependent// not dependent// error: declaration for dd not found}void f(int);double dd;void h(){g(2);g(’a’);// will cause one call of f(char) followed// by two calls of f(int)// will cause three calls of f(char)}—end example]10[Note: for purposes of name lookup, default arguments of function templates and default arguments ofmember functions of class templates are considered definitions (14.5).
—end note]14.6.1 Locally declared names1[temp.local]Within the scope of a class template, when the name of the template is neither qualified nor followed by <,it is equivalent to the name of the template followed by the template-parameters enclosed in <>. [Example: the constructor for Set can be referred to as Set() or Set<T>(). ] Other specializations (14.7.3) ofthe class can be referred to by explicitly qualifying the template name with the appropriate templatearguments. [Example:template<class T> class X {X* p;X<T>* p2;X<int>* p3;};// meaning X<T>—end example]2Within the scope of a class template specialization or partial specialization, when the name of the templateis neither qualified nor followed by <, it is equivalent to the name of the template followed by thetemplate-arguments enclosed in <>.
[Example:template<class T> class Y;template<> class Y<int> {Y* p;Y<char>* q;};260// meaning Y<int>// meaning Y<char>© ISO/IEC14 TemplatesISO/IEC 14882:1998(E)14.6.1 Locally declared names—end example]3The scope of a template-parameter extends from its point of declaration until the end of its template.
Atemplate-parameter hides any entity with the same name in the enclosing scope. [Note: this implies that atemplate-parameter can be used in the declaration of subsequent template-parameters and their defaultarguments but cannot be used in preceding template-parameters or their default arguments. For example,template<class T, T* p, class U = T> class X { /* ... */ };template<class T> void f(T* p = new T);This also implies that a template-parameter can be used in the specification of base classes.
For example,template<class T> class X : public Array<T> { /* ... */ };template<class T> class Y : public T { /* ... */ };The use of a template-parameter as a base class implies that a class used as a template-argument must bedefined and not just declared when the class template is instantiated. ]4A template-parameter shall not be redeclared within its scope (including nested scopes). A templateparameter shall not have the same name as the template name.
[Example:template<class T, int i> class Y {int T;// error: template-parameter redeclaredvoid f() {char T;// error: template-parameter redeclared}};template<class X> class X;// error: template-parameter redeclared—end example]5In the definition of a member of a class template that appears outside of the class template definition, thename of a member of this template hides the name of a template-parameter. [Example:template<class T> struct A {struct B { /* ... */ };void f();};template<class B> void A<B>::f() {B b;// A’s B, not the template parameter}—end example]6In the definition of a member of a class template that appears outside of the namespace containing the classtemplate definition, the name of a template-parameter hides the name of a member of this namespace.[Example:namespace N {class C { };template<class T> class B {void f(T);};}template<class C> void N::B<C>::f(C) {C b;// C is the template parameter, not N::C}—end example]7In the definition of a class template or in the definition of a member of such a template that appears outsideof the template definition, for each base class which does not depend on a template-parameter (14.6.2), ifthe name of the base class or the name of a member of the base class is the same as the name of a templateparameter, the base class name or member name hides the template-parameter name (3.3.7).
[Example:261ISO/IEC 14882:1998(E)14.6.1 Locally declared names© ISO/IEC14 Templatesstruct A {struct B { /* ... */ };int a;int Y;};template<class B, class a> struct X : A {B b;// A’s Ba b;// error: A’s a isn’t a type name};—end example]14.6.2 Dependent names1[temp.dep]Inside a template, some constructs have semantics which may differ from one instantiation to another.Such a construct depends on the template parameters. In particular, types and expressions may depend onthe type and or value of template parameters (as determined by the template arguments) and this determinesthe context for name lookup for certain names.
Expressions may be type-dependent (on the type of a template parameter) or value-dependent (on the value of a non-type template parameter). In an expression ofthe form:postfix-expression ( expression-listopt )where the postfix-expression is an identifier, the identifier denotes a dependent name if and only if any ofthe expressions in the expression-list is a type-dependent expression (14.6.2.2). If an operand of an operator is a type-dependent expression, the operator also denotes a dependent name. Such names are unboundand are looked up at the point of the template instantiation (14.6.4.1) in both the context of the templatedefinition and the context of the point of instantiation.2[Example:template<class T> struct X : B<T> {typename T::A* pa;void f(B<T>* pb) {static int i = B<T>::i;pb->j++;}};the base class name B<T>, the type name T::A, the names B<T>::i and pb->j explicitly depend on thetemplate-parameter.
—end example]3In the definition of a class template or in the definition of a member of such a template that appears outsideof the template definition, if a base class of this template depends on a template-parameter, the base classscope is not examined during name lookup until the class template is instantiated. [Example:typedef double A;template<class T> B {typedef int A;};template<class T> struct X : B<T> {A a;// a has type double};The type name A in the definition of X<T> binds to the typedef name defined in the global namespacescope, not to the typedef name defined in the base class B<T>. ]4If a base class is a dependent type, a member of that class cannot hide a name declared within a template, ora name from the template’s enclosing scopes. [Example:262© ISO/IECISO/IEC 14882:1998(E)14 Templates14.6.2 Dependent namesstruct A {struct B { /* ...
*/ };int a;int Y;};int a;template<class T> struct Y : T {struct B { /* ... */ };B b;void f(int i) { a = i; }Y* p;};// The B defined in Y// ::a// Y<T>Y<A> ya;The members A::B, A::a, and A::Y of the template argument A do not affect the binding of names inY<A>. ]14.6.2.1 Dependent types1[temp.dep.type]A type is dependent if it is— a template parameter,— a qualified-id with a nested-name-specifier which contains a class-name that names a dependent type orwhose unqualified-id names a dependent type,— a cv-qualified type where the cv-unqualified type is dependent,— a compound type constructed from any dependent type,— an array type constructed from any dependent type or whose size is specified by a constant expressionthat is value-dependent,— a template-id in which either the template name is a template parameter or any of the template arguments is a dependent type or an expression that is type-dependent or value-dependent.14.6.2.2 Type-dependent expressions[temp.dep.expr]1Except as described below, an expression is type-dependent if any subexpression is type-dependent.2this is type-dependent if the class type of the enclosing member function is dependent (14.6.2.1).3An id-expression is type-dependent if it contains:— an identifier that was declared with a dependent type,— a template-id that is dependent,— a conversion-function-id that specifies a dependent type,— a nested-name-specifier that contains a class-name that names a dependent type.Expressions of the following forms are type-dependent only if the type specified by the type-id, simpletype-specifier or new-type-id is dependent, even if any subexpression is type-dependent:263ISO/IEC 14882:1998(E)14.6.2.2 Type-dependent expressions© ISO/IEC14 Templatessimple-type-specifier ( expression-listopt )::opt new new-placementopt new-type-id new-initializeropt::opt new new-placementopt ( type-id ) new-initializeroptdynamic_cast < type-id > ( expression )static_cast < type-id > ( expression )const_cast < type-id > ( expression )reinterpret_cast < type-id > ( expression )( type-id ) cast-expression4Expressions of the following forms are never type-dependent (because the type of the expression cannot bedependent):literalpostfix-expression .
pseudo-destructor-namepostfix-expression -> pseudo-destructor-namesizeof unary-expressionsizeof ( type-id )typeid ( expression )typeid ( type-id )::opt delete cast-expression::opt delete [ ] cast-expressionthrow assignment-expressionopt14.6.2.3 Value-dependent expressions[temp.dep.constexpr]1Except as described below, a constant expression is value-dependent if any subexpression is valuedependent.2An identifier is value-dependent if it is:— a name declared with a dependent type,— the name of a non-type template parameter,— a constant with integral or enumeration type and is initialized with an expression that is valuedependent.Expressions of the following form are value-dependent if the unary-expression is type-dependent or thetype-id is dependent (even if sizeof unary-expression and sizeof ( type-id ) are not type-dependent):sizeof unary-expressionsizeof ( type-id )3Expressions of the following form are value-dependent if either the type-id or simple-type-specifier isdependent or the expression or cast-expression is value-dependent:simple-type-specifier ( expression-listopt )static_cast < type-id > ( expression )const_cast < type-id > ( expression )reinterpret_cast < type-id > ( expression )( type-id ) cast-expression14.6.2.4 Dependent template arguments[temp.dep.temp]1A type template-argument is dependent if the type it specifies is dependent.2An integral non-type template-argument is dependent if the constant expression it specifies is valuedependent.3A non-integral non-type template-argument is dependent if its type is dependent or it has either of the following forms264© ISO/IECISO/IEC 14882:1998(E)14 Templates14.6.2.4 Dependent template argumentsqualified-id& qualified-idand contains a nested-name-specifier which specifies a class-name that names a dependent type.4A template template-argument is dependent if it names a template-parameter or is a qualified-id with anested-name-specifier which contains a class-name that names a dependent type.14.6.3 Non-dependent names1[temp.nondep]Non-dependent names used in a template definition are found using the usual name lookup and bound at thepoint they are used.