<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On 4 February 2018 at 18:40, Łukasz Kucharski via cfe-dev <span dir="ltr"><<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">I hope this is a good audience.<br>
<br>
Title seems long an convoluted, but the problem boiled down to gcc and<br>
clang disagreeing on such code:<br>
<br>
(This is a grokked version of code which we got during a real world<br>
code-base evolution [if that means anything])<br>
```<br>
#include <type_traits><br>
#include <iostream><br>
#include <string><br>
<br>
template <typename T><br>
struct B {<br>
    template <typename U><br>
    using nested_templated_using = U;<br>
<br>
    template<typename U = T, nested_templated_using<U>* = nullptr ><br>
    void f();<br>
};<br>
<br>
template <typename T><br>
template <typename U, typename B<T>::template nested_templated_using<U>* ><br>
//                   ^ should typename be here or not?<br>
void  B<T>::f(){ }<br>
<br>
int main () { return 0;}<br>
```<br>
[godbolt example](<a href="https://godbolt.org/g/yjPH1u" rel="noreferrer" target="_blank">https://godbolt.org/<wbr>g/yjPH1u</a>)<br>
<br>
 clang requires `typename` keyword in the indicated spot, while gcc<br>
forbids it. They error out with the same message indicating that the<br>
out-of-line definition does not match declaration.<br></blockquote><div><br></div><div>Strictly-speaking, neither is formally correct. For a type involving template parameters, the two must be spelled with the same sequence of tokens (though implementations are allowed to accept additional cases); see [temp.over.link]. So the right thing is:<br></div><div><br></div><div><div>template <typename T></div><div>struct B {</div><div>    template <typename U></div><div>    using nested_templated_using = U;</div><div><br></div><div>    template<typename U = T, typename B<T>::template nested_templated_using<U>* = nullptr ></div><div>    void f();</div><div>};</div><div><br></div><div>template <typename T></div><div>template <typename U, typename B<T>::template nested_templated_using<U>* ></div><div>void  B<T>::f(){ }<br></div></div><div><br></div><div>... which Clang and MSVC accept and GCC rejects. (ICC/EDG seems to reject every variation on this.) However, the intent is to permit additional cases where the equivalence of the two declarations can be determined using information from the template itself (see CWG issue 2, wg21.link/cwg2), which also permits your original example.</div><div><br></div><div>So we can at least conclude that GCC is wrong to reject your original example. Presumably within the class definition it canonicalizes the type of the template parameter to merely "U *", and is unable to match that up against the "typename B<T>::template nested_templated_using<U> *" within the out-of-class definition of f.<br></div><div><br></div><div>But that leaves open the question of whether the code without the typename/template keywords is valid too. See below!</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">I've asked this question on<br>
[stackoverflow](<a href="https://stackoverflow.com/questions/48448353" rel="noreferrer" target="_blank">https://<wbr>stackoverflow.com/questions/<wbr>48448353</a>) but it<br>
wasn't clear yet what is the core issue, I thought gcc misbehaves.<br>
<br>
I got some great input by Johannes Schaub, who pointed [CWG issue<br>
#2](<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2" rel="noreferrer" target="_blank">http://www.open-std.org/<wbr>jtc1/sc22/wg21/docs/cwg_<wbr>active.html#2</a>) and<br>
[CWG issue #560](<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#560" rel="noreferrer" target="_blank">http://www.open-std.org/<wbr>jtc1/sc22/wg21/docs/cwg_<wbr>active.html#560</a>).<br>
They both treat about referring to the dependent types, though as the<br>
type of return value.<br>
<br>
My thoughts are:<br>
1. The type of the parameter is dependent.<br>
2. I am not sure whether the type of the parameter is "a member of the<br>
current instantiation" as understood in<br>
[temp.res#3](<a href="http://eel.is/c++draft/temp.res#3" rel="noreferrer" target="_blank">http://eel.is/c++<wbr>draft/temp.res#3</a>)<br></blockquote><div><br></div><div>This is the right question. And, sadly, the standard is unclear on this question; [temp.dep.type] says this depends on whether the name appears "in the definition of [...] a member of a class template", but is the template-parameter-list "in the definition" or not? The answer is by no means obvious.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
3. In conjunction with [temp.res#5](<a href="http://eel.is/c++draft/temp.res#5" rel="noreferrer" target="_blank">http://eel.is/c++<wbr>draft/temp.res#5</a>)<br>
above renders "wrong guess" about the presence of the keyword a killer<br>
- program is ill-formed.<br>
<br>
I might be wrong in my toughts, and I am not sure whether, or not,<br>
`typename` keyword usage changes for non-type template parameters.<br>
Also, inline definition does not require the keyword.<br>
<br>
It would be nice if someone could give authoritative answer<br>
(preferably stepping through standard) whether:<br>
1. clang is wrong.<br>
2. gcc is wrong.<br>
3. standard is unclear.<br>
<br>
Regards,<br>
Łukasz.<br>
______________________________<wbr>_________________<br>
cfe-dev mailing list<br>
<a href="mailto:cfe-dev@lists.llvm.org">cfe-dev@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/cfe-dev</a><br>
</blockquote></div><br></div></div>