问题
Why is that case incorrect (it's logical)
template <typename T>
struct Der: public Base
{
typedef int T;
T val;
};
, but that case is correct?
struct Base
{
typedef int T;
};
template <typename T>
struct Der: public Base
{
T val;
};
The Standard 14.6.1/7 says:
In the definition of a class template or in the definition of a member of such a template that appears outside of the template definition, for each base class which does not depend on a template-parameter (14.6.2), if the name of the base class or the name of a member of the base class is the same as the name of a template-parameter, the base class name or member name hides the template-parameter name (3.3.7).
Why is it not ambiguous in here?
回答1:
The first example is incorrect according to [temp.local]/6:
A template-parameter shall not be redeclared within its scope (including nested scopes).
However, in
template <typename T>
struct Der: public Base
{
T val;
};
T
is hidden by the name inherited from Base
- as specified by your quote.
[..] if the name of the base class or the name of a member of the base class is the same as the name of a template-parameter, the base class name or member name hides the template-parameter name (3.3.7).
That is, the member val
is of type int
. Demo.
回答2:
In general, the standard tries to ensure that the meaning of a type in a given scope is the same.
If we pretend that the typedef is allowed then consider the types of val1
, val2
, and val3
in the following?
template <typename T>
struct Der: public Base
{
void f1() {
T val1; // What is the type of 'val1'?
}
T val2; // What is the type of 'val2'?
typedef int T;
T val3; // What is the type of 'val3'?
};
The only variable to have the template parameter type T would be 'val2'.
This is because the standard requires that all members of the class be "in scope" for f1
. This is why member functions can refer to member variables defined later in the class body.
The same problem can be demonstrated with typedefs too:
typedef int T;
struct S
{
T x;
typedef float T;
T y;
};
Again, if this was legal then the T
used for the declaration of x
would refer to ::T
and the T
used for y
would refer to typedef S::T
.
This is covered by the standard under ISO 3.3.7/1:
The following rules describe the scope of names declared in classes.
...
2) A name N used in a class S shall refer to the same declaration in its context and when re-evaluated in the completed scope of S. No diagnostic is required for a violation of this rule.
回答3:
Because the second is unambigous:
You might not care or know that there was the typedev int T
in the superclass, but you've just introduced T
as template parameter, which makes it clear that you're referring to it when using T
in Der
.
来源:https://stackoverflow.com/questions/28029722/typedef-and-template-parameter-with-same-name