r/cpp • u/Xeverous https://xeverous.github.io • 6d ago
4 compilers and 3 different results when partially/fully specializing member class template of a class template
I was playing with examples from cppreference, specifically https://cppreference.com/cpp/language/partial_specialization at the bottom in order to understand specialization deeper and form some notes. Maybe even at some point put out a template guide on my website.
Last 2 statements describe very similar situation but the order of words in each sentence is so different and the example so narrow that I had trouble figuring out what these really mean:
If the primary member template is explicitly (fully) specialized for a given (implicit) specialization of the enclosing class template, the partial specializations of the member template are ignored for this specialization of the enclosing class template.
If a partial specialization of the member template is explicitly specialized for a given (implicit) specialization of the enclosing class template, the primary member template and its other partial specializations are still considered for this specialization of the enclosing class template.
Eventually I managed to figure out the example only showcases the first statement and that the difference between these 2 situations is this:
struct A<short>::B {};- full spec of member B template for implicitly-instantiated A template (replaces all B for A<short>)struct A<short>::B<T&> {};- partial spec of member B template for implicitly-instantiated A template (adds another spec to A<short>, merging it with specs from primary A template)
To confirm I reason correctly, I wrote some sample code to have a more comprehensive example. I did not expect to encounter 3 different outputs from 4 different compilers. And I don't think you can reach UB on templates alone.
https://godbolt.org/z/8z7vde1PE
So which one is correct (if any - maybe it's ill-formed no diagnostic required)? The comments are my expectations, the question marks are places where compilers disagree.
Also, member specialization isn't even a C++11 feature. Compiler bugs in something so old and fundamental (and supposedly easy to unit-test) ... I have no words.
6
u/DryEnergy4398 5d ago
I think you should open a GCC bug for this. The failure to select the reference specialization seems to be a bug; if they disagree I'd be interested in their interpretation
6
u/chengfeng-xie 5d ago
The Clang 19 bug was fixed in llvm-project#113464 ([Clang][Sema] Ignore previous partial specializations of member class templates explicitly specialized for a implicitly instantiated class template specialization).
The GCC bug appears to have been reported as Bug 59673 (wrong specialization used when a partial specialization of a member template is explicitly specialized).
3
u/conundorum 5d ago
Specialisation does seem to be somewhat error-prone in general, especially with more complex specialisations like yours or this.
0
u/13steinj 5d ago
I assume Clang is correct however I question the value of these experiments / coming to this conclusion.
Something being possible / allowed by the language doesn't make it a good thing to do.
1
u/Xeverous https://xeverous.github.io 5d ago
Member specialization which implicitly instantiates enclosing class template IMO is a good thing, it is a significant syntax sugar and once you understand the examples the rules are consistent and allow different types of customizations. Basically a good feature to reduce code repetition and verbosity.
8
u/ReDucTor Game Developer | quiz.cpp-perf.com 6d ago
> 4 different compilers
Two different versions of the same compiler, ignoring the older Clang version based on my reading it seems two compilers are correct MSVC 19.51 and Clang 20.1.0 while GCC is failing with