<div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div dir="ltr">On Mon, Apr 29, 2019 at 5:46 AM Lorenzo Cavallini 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-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div dir="ltr"><div>Hello everyone,</div><div>I'm writing to report what I think is an issue related to Class Template Argument Deduction (CTAD for short). Compiling this short snippet:</div><div><br></div><div><font size="1"><span style="font-family:monospace,monospace">#include <cstdio><br>#include <vector><br><br>template<typename T><br>void printV(const std::vector<T>& v)<br>{<br> if (v.size() == 1) {<br> printf("%d ", v[0]);<br> return;<br> }<br> int middle = v.size()/2;<br> printV(std::vector{v.begin(), v.end()+middle});<br>}<br><br>int main()<br>{<br> std::vector<int> v = {10,1};<br> printV(v);<br> return 0;<br>}</span></font></div><div><font size="1"><span style="font-family:monospace,monospace"><br></span></font></div><div><font size="1"><span style="font-family:monospace,monospace"><font size="2"><font face="arial,helvetica,sans-serif">will
result in clang generating an infinite error report (at least, I left it running for several hours, then I stopped the process...), due to (I guess)
wrongly deducted template arguments.</font></font></span></font></div></div></div></blockquote><div><br></div><div>The Clang issue is not related to CTAD. You can achieve the same "infinite" error message via explicitly (wrongly) supplied template arguments, too. Just replace</div><div><br></div><div><span style="font-family:monospace,monospace;font-size:x-small"> printV(std::vector{v.begin(), v.end()+middle});</span><br></div><div>with</div><div><span style="font-family:monospace,monospace;font-size:x-small"><br></span></div><div><span style="font-family:monospace,monospace;font-size:x-small"> using VI = std::vector<typename std::vector<T>::const_iterator>;</span></div><div><span style="font-family:monospace,monospace;font-size:x-small"> printV(VI{v.begin(), v.end()+middle});</span><br></div><div><br></div><div>By the way, CTAD is behaving as intended here: you gave an initializer-list of const_iterators, and so you get a vector of const_iterators. If you didn't want a vector of const_iterators, you should have used the sequence-container-constructor syntax (round parens), not the braced-initializer-list syntax (braces).</div><div>See also <a href="https://quuxplusone.github.io/blog/2018/12/09/wctad/">"<i>Contra</i> CTAD"</a> and <a href="https://quuxplusone.github.io/blog/2019/02/18/knightmare-of-initialization/">"The Knightmare of Initialization in C++"</a>.</div><div><br></div><div>Here's an ultra-reduced test case.</div><div><br></div><div><p style="margin:0px;font-stretch:normal;font-size:13px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures">[[nodiscard]] int dummy();</span></p><p style="margin:0px;font-stretch:normal;font-size:13px;line-height:normal;font-family:Menlo;min-height:15px"><span style="font-variant-ligatures:no-common-ligatures"></span><br></p><p style="margin:0px;font-stretch:normal;font-size:13px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures">template<class T></span></p><p style="margin:0px;font-stretch:normal;font-size:13px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures">void printV(T t) {</span></p><p style="margin:0px;font-stretch:normal;font-size:13px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures"> dummy();</span></p><p style="margin:0px;font-stretch:normal;font-size:13px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures"> printV(&t);</span></p><p style="margin:0px;font-stretch:normal;font-size:13px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures">}</span></p><p style="margin:0px;font-stretch:normal;font-size:13px;line-height:normal;font-family:Menlo;min-height:15px"><span style="font-variant-ligatures:no-common-ligatures"></span><br></p><p style="margin:0px;font-stretch:normal;font-size:13px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures">int main() {</span></p><p style="margin:0px;font-stretch:normal;font-size:13px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures"> printV(42);</span></p><p style="margin:0px;font-stretch:normal;font-size:13px;line-height:normal;font-family:Menlo">
</p><p style="margin:0px;font-stretch:normal;font-size:13px;line-height:normal;font-family:Menlo"><span style="font-variant-ligatures:no-common-ligatures">}</span></p></div><div><br></div><div>The same O(1024^2) lines of error output are produced, but much faster, because Clang doesn't have to instantiate all those nested template types (or render their names in the error messages).</div><div><br></div><div>I think it might be convenient if Clang lowered the nested template limit from 1024 to, say, 32, in the case that a warning or error message has been produced already.</div><div><br></div><div>–Arthur</div></div></div></div></div></div></div></div></div>