Document number: |
00-0056/N1279 |
Date: |
November 1, 2000 |
Author: |
John Spicer, Edison Design Group |
|
jhs@edg.com |
Definition of Dependent Name - Revision 2
Introduction
This document contains the proposed working paper changes for
the definition of dependent name.
(See core issue #224). This is a revision of N1251.
This issue was described in detail in N1231.
At the Tokyo meeting, the core group agreed on the direction proposed
in N1231, that the "dependency" of a name should be based on its type,
and not on the form of reference used, and that special rules are needed
to get the desired behavior when referring to names declared within the
class template itself.
N1251 proposed specific working paper changes. These changes were reviewed
in Toronto. In addition, several drafts of this document were also reviewed
in Toronto. This document incorporates the changes resulting from those
reviews.
Proposed Changes
Replace section 14.6.2.1 (_temp.dep.type_) with the following:
In the definition of a class template, a nested class of a class template,
a member of a class template, or a member of a nested class of a class
template, a name refers to the current instantiation if it is
-
the injected-class-name (_class_) of the class template, or nested class,
-
in the definition of a primary class template, the name of the class
template followed by the template argument list of the primary template
(as described below) enclosed in <>,
-
in the definition of a nested class of a class template, the name
of the nested class referenced as a member of the current instantiation, or
-
in the definition of a partial specialization, the name of the class
template followed by the template argument list of the partial
specialization enclosed in <>.
The template argument list of a primary template is a template argument
list in which the nth template argument has the value of the
nth template parameter of the class template.
A template argument that is equivalent to a template parameter
(i.e., has the same constant value or the same type as the template
parameter)
can be used in place of that template parameter in a reference to the
current instantiation. In the case of a nontype template argument,
the argument must have been given the value of the template parameter
and not an expression involving the template parameter.
[Example:
template class A {
A* p1; // A is the current instantiation
A* p2; // A is the current instantiation
A p3; // A is not the current instantiation
::A* p4; // ::A is the current instantiation
class B {
B* p1; // B is the current instantiation
A::B* p2; // A::B is the current instantiation
typename A::B* p3; // A::B is not the
// current instantiation
};
};
template class A {
A* p1; // A is the current instantiation
A* p2; // A is not the current instantiation
};
template struct B {
B* b1; // refers to the current instantiation
B* b2; // not the current instantiation
typedef T1 my_T1;
static const int my_I = I;
static const int my_I2 = I+0;
static const int my_I3 = my_I;
B* b3; // refers to the current instantiation
B* b4; // not the current instantiation
B* b5; // refers to the current instantiation
};
--end example]
A name is a member of the current instantiation if it is
-
An unqualified name that, when looked up, refers to a member of a class
template.
[Note: This can only occur when looking up a name in a scope enclosed
by the definition of a class template.]
-
A qualified-id in which the nested-name-specifier
refers to the current instantiation.
[Example:
template class A {
static const int i = 5;
int n1[i]; // i refers to a member of the current instantiation
int n2[A::i]; // A::i refers to a member of the current instantiation
int n3[A::i]; // A::i refers to a member of the current instantiation
int f();
};
template int A::f()
{
return i; // i refers to a member of the current instantiation
}
--end example]
A name is a member of an unknown specialization if the name
is a qualified-id in which the nested-name-specifier
names a dependent type that is not the current instantiation.
A type is dependent if it is
-
a template parameter,
-
a member of an unknown specialization,
-
a nested class that is a member of the current instantiation,
-
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 expression that is value-dependent, or
-
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.
[Note: Because typedefs do not introduce new types, but instead
simply refer to other types, a name that refers to a typedef that is a
member of the current instantiation is dependent only if the type referred
to is dependent.]
In 14.6.2.2:
Replace
-
a nested-name-specifier that contains a class-name that
names a dependent type.
with
- a nested-name-specifier or qualified-id that names
a member of an unknown specialization
Add the following paragraph:
A class member access expression (_expr.ref_) is type-dependent
if the type of the referenced member is dependent.
[Note: In an expression of the form x.y
or
xp->y
the type of the expression is usually the type of
the member y
of class of x
(or the class
pointed to by xp
). However, if x
or
xp
refers to a dependent type that is not the current
instantiation, the type of y
is always dependent. If
x
or xp
refers to a non-dependent type or
refers to the current instantiation, the type of y
is the
type of the class member access expression.]
In 14.6 paragraph 3:
Replace
A qualified-name that refers to a type and that depends on
a template-parameter (_temp.dep_) shall be prefixed by
the keyword typename.
with
A qualified-name that refers to a type and that depends on
a template-parameter (_temp.dep_) but does not refer to a
member of the current instantiation shall be prefixed by
the keyword typename.
In 14.2 paragraph 4:
Replace
When the name of a member template specialization appears after
. or -> in a postfix-expression, or after
nested-name-specifier in a qualified-id, and the
postfix-expression or qualified-id explicitly
depends on a template-parameter (_temp.dep_), the member
template name must be prefixed by the keyword
template. Otherwise the name is assumed to name a
non-template.
with
When the name of a member template specialization appears after
. or -> in a postfix-expression, or after
nested-name-specifier in a qualified-id, and the
postfix-expression or qualified-id explicitly
depends on a template-parameter (_temp.dep_) but does not
refer to a member of the current instantiation (_temp_dep_type_), the member
template name must be prefixed by the keyword
template. Otherwise the name is assumed to name a
non-template.
In 14.6.1 paragraph 2:
Remove the following text, which was added for issue 108. The updated
definition of dependent name now addresses this case.
Within the scope of a class template, when the unqualified name of a
nested class of the class template is referred to, it is
equivalent to the name of the nested class qualified by the name
of the enclosing class template.
[Example:
template struct A {
class B {};
// B is equivalent to A::B, which is equivalent to A::B,
// which is dependent.
class C : B { };
};
--end example]
End of document.