Gcc compiles this fine, but Clang (trunk) refuses with the message:
<source>:7:8: error: class template partial specialization is not more specialized than the primary template [-Winvalid-partial-specialization]
https://godbolt.org/g/h8rsWC
template<class T, T x>
struct S{};
template<int& x>
struct S<int&, x> { };
Is this code correct or not?
This only manifests in -std=c++17
and later. The "more specialized" determination requires synthesizing a pair of function templates from the class templates, synthesizing unique types, values, and templates for the template parameters, and finally performing template argument deduction in both directions. A template is "more specialized" if deduction succeeds in one direction but not the other.
Here, Clang is deducing T
from two sources and getting divergent results:
int&
, it deduces T := int&
.x
, it deduces T := int
per the usual deduction rules (which generally do not deduce a reference type). This ability to deduce from the type of a non-type template argument was added in C++17.This makes the deduction fail in both directions, so the partial specialization fails the "more specialized" test.
This looks like a defect in the standard. The workaround is to wrap the T
in the original template in a non-deduced context.
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