This code compiles fine on Clang and Visual C++ but not on GCC:
#include <iostream>
template <class T>
struct Test {
Test(T &t) : _t(t) {
}
void method() {
std::cout << _t.Internal::_value << "\n"; // Doesn't work on GCC
std::cout << _t.T::Internal::_value << "\n"; // Work on all compilers
}
private:
T &_t;
};
template <class T>
struct Base {
T _value = 1;
};
template <class T>
struct Child : Base<int> {
using Internal = Base<int>;
int _value = 2;
};
int main(int argc, const char * argv[]) {
Child<float> child;
Test<Child<float>> test(child);
test.method();
return 0;
}
The error message from GCC is
error: 'Internal' has not been declared
9 | std::cout << _t.Internal::_value << "\n";
| ^~~~~~~~
Which one is right ?
Visual C++ and Clang are right in accepting this code.
It was a bug in GCC that prevented it from doing the same. The error as in the question was up to GCC 10, in GCC 11 its wording changed to
error: request for member 'Internal' in non-class type 'T'
9 | std::cout << _t.Internal::_value << "\n";
| ^~~~~~~~
And GCC trunk finally accepts the code as well. Demo: https://gcc.godbolt.org/z/dj34Yhns3
So we could expect the fix in GCC 12.