Open kamrann opened 2 months ago
@llvm/issue-subscribers-clang-frontend
Author: Cameron Angus (kamrann)
So I think clang is correct here, it is interesting to note that clang accepts this if we change the member s
to not have an deduced type: https://godbolt.org/z/fEfP4b1rb
although edg/MSVC do not accept in this case. gcc is the only one to accept in either case.
We used to have: https://timsong-cpp.github.io/cppwp/n4140/temp.explicit#10
which I believe was changed by: https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1815r2
and I think the wording to consider here is now: https://eel.is/c++draft/temp.inst#1
but maybe I am off.
CC @zygoloid @AaronBallman @hubert-reinterpretcast @cor3ntin
Ok, yep the more I think about it the more I suspect there is something off in my understanding of what exactly extern template
is supposed to do, specifically in the case of class templates. And/or there is perhaps an element of the terminology being somewhat inconsistent or unclear.
it is interesting to note that clang accepts this if we change the member s to not have an deduced type
Hmm, perhaps I oversimplified things when reducing the repro then since in my original case it was not triggered by a static member variable like above, but a more complex case with a class member function. But I think it was inline, so perhaps it's the same rule that applies.
My confusion stems from a lot of the literature stating that extern template
can be used to reduce compilation time by preventing the compiler from instantiating a template in all translation units. It seems either this is plain incorrect, or it comes down to what exactly is meant by 'instantiating'. Am I right in now suspecting that for class templates, there is a minimal level of instantiation that must always be done regardless, and extern template
is only suppressing things further on in the compilation process relating to emission of symbols and code generation?
Clang is probably not wrong, but for convoluted or tenuous reasons: https://eel.is/c++draft/temp.explicit#9 says that the explicit instantiation declaration for the class specialization is also an explicit instantiation declaration of each of its direct non-template members. Applying this in the straightforward manner requires the class to be complete.
Note: Explicit instantiation declarations do not only affect implicit instantiaton: they also affect whether an explicit specialization can be declared later; see https://eel.is/c++draft/temp.spec#general-5.
The following is rejected by clang (and appears to have always been so). GCC accepts it.
Compiler explorer: https://godbolt.org/z/qTssnz68s
Why would the
extern template
line, which is an explicit instantiation declaration only, trigger the instantiation? Isn't the whole point of such a declaration to prevent unwanted instantiations?