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::B
shall be resolved to variable rather thanstruct B
, these rules are listed in the following:The above rule says that the name of
struct B
was hidden by the name of declarationint B = 20;
The above rule says that the keyword
typename
does not affect the result ofqualified name lookup
, In other words, the keywordtypename
does not require that the name lookup procedure only finds types.So, in the scope of
A
, the declarations ofint B = 20;
andstruct B
are 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.3
but also the higher versions are all wrong.