Here is a program I am trying to compile.
template <typename T>
struct A
{
    T foo() const
    {
        return 1;
    }
};
template <typename T>
struct B : A<T>
{
    using U = A<T>;
    T foo() const
    {
        return 2;
    }
};
template <typename T>
struct D
{
    B<T> b;
    int foo() const
    {
        // using U = typename B<T>::U; // compilation succeeds if I uncomment this line
        return b.U::foo();
    }
};
int main()
{
    D<int> d;
    return d.foo();
}
I see different behaviour across gcc 9.2, clang 9.0.0 and icc19.0.1.
The program fails to compile with gcc giving an error U has not been declared, compiles fine with clang and has a non-trivial assembly with icc.
Why is the behaviour different across these compilers?
I tried reading dependent_name but gave up since I couldn't follow it properly. From what little I understand, data member b inside struct D has a dependent type and U should have been resolved when the template is instantiated.
Compiled the above code with the above compilers on godbolt.org here: https://godbolt.org/z/n_Wl44. I used C++17 with -O3 flag. Thanks in advance!!!
U in b.U::foo(); should be looked up during instantiation in the context of B<T> first, finding using U = A<T>;, so that b.U::foo() calls foo() defined in A<T>. [basic.lookup.classref]/4
The lookup should be delayed until instantiation and no lookup at definition should happen, because b is dependent as its type depends on the template parameter T. [temp.dep.expr]/5
Therefore this seems to be a bug in GCC. A very similar code example has been posted in this bug report, which demonstrates the same issue as far as I can tell. The bug is currently marked status "new".
As far as I can tell the other failing compilers shown in the godbolt.org conformance view posted by @TedLyngmo are derivatives of GCC, so it is not like independent compilers are disagreeing on this.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With