c++templatesinheritancename-lookupdependent-name

Different compiler behaviour when using alias as scope to get parent member


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 ?


Solution

  • 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.