Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using incomplete type in a member function of a class template

GCC (8.3, 9.1), Clang (7, 8) and MSVC (19.20) differ is their ability to compile this code:

struct C;

template<typename T> struct S {
    void foo() {
        // C2 c;
        C c;
    }
};

class C {};

int main() {
    S<int> s;
    s.foo();
    return 0;
}

GCC and MSVC accept it, whereas Clang rejects it. Clang rejects it even if I make foo itself a template and/or do not call it at all.

My understanding is that foo is not instantiated unless it is called, and it is instantiated at the point where it is called. At that point C is complete, and the code should compile. Is this a reasoning of GCC?

As a side note, if foo is not called, MSVC accepts the code even if I replace C with an undeclared C2 inside foo - in this case it seems to just check the function body to be syntactically correct.

Which behaviour is correct according to the Standard? If it is Clang's, why does the Standard forbids the flexibility that GCC gives?

like image 309
Evg Avatar asked May 07 '19 14:05

Evg


1 Answers

This is ill-formed, no diagnostic required, due to [temp.res]/8:

The program is ill-formed, no diagnostic required, if:

  • [...]
  • a hypothetical instantiation of a template immediately following its definition would be ill-formed due to a construct that does not depend on a template parameter, or [...]
  • [...]

So the whole program is bad, but implementations aren't required to diagnose it. Clang does, which is good for clang, gcc and MSVC don't, which isn't wrong.

like image 192
Barry Avatar answered Nov 03 '22 22:11

Barry