Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

typedef and template parameter with same name

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?

like image 794
Denis Avatar asked Jan 19 '15 16:01

Denis


People also ask

Can template have default parameters?

Template parameters may have default arguments. The set of default template arguments accumulates over all declarations of a given template.

Which parameter is allowed for non-type 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.

Can a template be a template parameter?

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.)

What is typename in template?

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.


2 Answers

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.

like image 145
Columbo Avatar answered Sep 21 '22 04:09

Columbo


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.

like image 25
Richard Corden Avatar answered Sep 22 '22 04:09

Richard Corden