<div dir="ltr"><div dir="ltr">On Tue, 28 May 2019 at 16:17, Arthur O'Dwyer via cfe-dev <<a href="mailto:cfe-dev@lists.llvm.org">cfe-dev@lists.llvm.org</a>> wrote:<br></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr">On Tue, May 28, 2019 at 9:01 AM via cfe-dev <<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a>> wrote:<br></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Please consider the example here:<br>
<br>
<a href="https://godbolt.org/z/4AwrXz" rel="noreferrer" target="_blank">https://godbolt.org/z/4AwrXz</a><br>
<br>
Clang up to version 3.9.1 and all recent versions of other compilers accept the code. Clang version >=4.0 fails.<br>
If you move the definition of AccessorPointersT to Foo, it works again and the partial specialization is deduced correctly.<br>
Is this a bug or a pedantic interpretation of the c++ standard by clang?<br></blockquote><div><br></div><div>Well, the compiler appears to be right that the partial specialization is unreachable because the `IsConst` parameter can't be deduced.</div><div>Suppose you instantiated `Foo<A>`, where `A` was a class type defined as</div><div><br></div><div><div style="color:rgb(0,0,0);background-color:rgb(255,255,254)"><div><font face="courier new, monospace"><span style="color:rgb(0,0,255)">struct </span>A {};</font></div><div><font face="courier new, monospace"><span style="color:rgb(0,0,255)">template</span><> <span style="color:rgb(0,0,255)">struct </span>Bar<A> {</font></div><div><font face="courier new, monospace"><span style="color:rgb(0,0,255)">    template</span><<span style="color:rgb(0,0,255)">bool</span>> <span style="color:rgb(0,0,255)">using </span>AccessorPointersT = <span style="color:rgb(0,0,255)">int</span>;</font></div><div><font face="courier new, monospace">};</font></div></div></div><div><br></div><div>Then `Foo<A>::AccessorPointersT<false>` and `Foo<A>::AccessorPointersT<true>` denote the same type (namely, `int`). So you can't use template "pattern matching" to differentiate them, because they're identical.</div><div><br></div><div>(Would you expect the partial specialization to be chosen in this case? If so, what would you expect it to deduce for the actual value of `IsConst`?)</div><div><br></div><div>If you move the definition of the AccessorPointers struct from Bar down into Foo, then I believe the problem goes away, as you indicate. In that case, `Foo<A>::AccessorPointersT<false>` and `Foo<A>::AccessorPointersT<true>` definitely denote different types, and so it's OK to use pattern matching on them.</div></div></div></div></div></div></blockquote><div><br></div><div>Instantiating Foo<A> for the above A would be ill-formed. But Foo itself is not, because it has valid instantiations (eg, Foo<int>).<br></div><div><br></div><div>It looks like we fail to properly take the deduction depth into account when checking for deducibility of a dependent template specialization type, and incorrectly treat all dependent-scope template specialization types as non-deducible (rather than being "dependently deducible"). :(</div></div></div>