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?
Template parameters may have default arguments. The set of default template arguments accumulates over all declarations of a given template.
Which parameter is legal for non-type template? Explanation: The following are legal for non-type template parameters:integral or enumeration type, Pointer to object or pointer to function, Reference to object or reference to function, Pointer to member.
A template argument for a template template parameter is the name of a class template. When the compiler tries to find a template to match the template template argument, it only considers primary class templates. (A primary template is the template that is being specialized.)
In template definitions, typename provides a hint to the compiler that an unknown identifier is a type. In template parameter lists, it's used to specify a type parameter.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With