Let's consider the following demonstrative program.
#include <iostream>
struct A
{
struct B
{
int b = 10;
};
int B = 20;
};
template <class T>
struct C
{
void f() const
{
typename /*struct*/ T::B b;
int x = b.b;
std::cout << "x == " << x << '\n';
}
};
int main()
{
C<A>().f();
}
As it is seen the declaration of the member struct B in the structure A is hidden by the declaration of the data member B having the type int.
So in the function definition of the template structure declaration
typename /*struct*/ T::B b;
the depended name T::B should not be found.
However the compiler gcc 8.3 compiles the program successfully and the program outputs
x == 10
On the other hand, the compiler Visual C++ 2019 is not going to compile the program and issues a syntax error.
So is it a bug of the compiler gcc 8.3?
The second problem is that it would be natural if such a construction (with uncommented keyword struct) with an elaborated type specifier would be allowed.
typename struct T::B b;
However the both compilers consider the construction as incorrect.
Is it indeed incorrect?
It should be a bug of the compiler gcc 8.3. Because the standard rule that
typename T::Bshall be resolved to variable rather thanstruct B, these rules are listed in the following:The above rule says that the name of
struct Bwas hidden by the name of declarationint B = 20;The above rule says that the keyword
typenamedoes not affect the result ofqualified name lookup, In other words, the keywordtypenamedoes not require that the name lookup procedure only finds types.So, in the scope of
A, the declarations ofint B = 20;andstruct Bare all found, and then the variable hidesclass name. So, according to rule If the qualified-id in a typename-specifier does not denote a type or a class template, the program is ill-formed, the program should be ill-formed. Hence, GCC 8.3 is wrong.In addition, not only
GCC 8.3but also the higher versions are all wrong.