14

The following bit of code compiles in VS2008 and GCC 4.8.2

template<typename T=void>
struct Foo
{
};

// typedef Foo<> Foo;   // Does *NOT* compile

int main()
{
    typedef Foo<> Foo;
    Foo f1;

   // Foo<char> f2;     // Does *NOT* compile
   //::Foo<char> f3;    // COMPILES
}

Is it valid?

Olumide
  • 5,397
  • 10
  • 55
  • 104

2 Answers2

17

As per C++11 3.3.10/1:

A name can be hidden by an explicit declaration of that same name in a nested declarative region or derived class.

(Emphasis mine)

That's why the template name Foo can be hidden by the typedef name Foo inside main() (a different scope), but not in the same scope as the template name is declared.

As to why this similar case is legal:

struct Foo
{
};

typedef Foo Foo;   // *DOES* compile

That is explicitly allowed by 7.1.3/3:

In a given non-class scope, a typedef specifier can be used to redefine the name of any type declared in that scope to refer to the type to which it already refers.

Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
11

Yes it's valid, for the same reason that this is valid:

struct Foo { };

namespace bar {
    struct Foo { };
}

You're just overwriting the name in a different scope. Inside of main, you can still do something like:

::Foo<int> f2;
Barry
  • 286,269
  • 29
  • 621
  • 977