This question depends on what is called injected-class-name. From the class]
The class name is inserted into the area in which it is declared immediately after viewing the class name. The class name is also inserted into the scope of the class itself; this is known as the name of the introduced class. To verify access, the name of the entered class is considered as the name of the public member.
And from [temp.local]:
Like regular (non-template) classes, class templates have a name with the class introduced (section 9). The name of the entered class can be used as a template name or type name. When used with a list argument template, as a template argument for a template template, or as the ending identifier in a specifier of a specified type declaration of a friend’s class template, it refers to the class template itself. Otherwise, it is equivalent to the template name, followed by the template parameters of the class template enclosed in <> .
That is, in the definitions of Bar1<T> or Bar2<T> you can use Bar1 or Bar2 to indicate the full type of the class. That is, these declarations are equivalent:
void Foo(Bar2<T> const & other); void Foo(Bar2 const & other);
However, the search rules apply as usual. Although Base has the name of the entered class, it is a dependent name and therefore cannot be found using normal unqualified searches. From [temp.dep]:
In the definition of a class template or class, the domain of the dependent base class (14.6.2.1) is not considered during the search for an unqualified name, either at the definition point of a class template or member, or during the creation of a template or class member.
what does it do:
Bar1() : Base() {}
poorly educated. Base is an unqualified search, and there is no such name Base . There is Base<T>::Base (there is the name of the entered class), but this area has not been studied. You will have to either perform a qualified search:
Bar1() : Bar1<T>::Base() {} Bar1() : Bar1::Base() { }
or not rely on the name of the entered Base class:
Bar1() : Base<T>() { }
VS mistakenly accepts Bar1 . Bar2 excellent if in more detail than possible. There is nothing wrong.
It is also worth noting that if the base was not dependent, you could still use its injected class name, even if it was a template:
template <class T> struct Base { }; struct Derived : Base<int> { Derived() : Base() { }