[cfe-dev] Class Template Argument Deduction failure

Nicolas Lesser via cfe-dev cfe-dev at lists.llvm.org
Mon Apr 29 07:13:14 PDT 2019

Lorenzo Cavallini via cfe-dev wrote:
> Hello everyone,
> I'm writing to report what I think is an issue related to Class Template
> Argument Deduction (CTAD for short). Compiling this short snippet:
> #include <cstdio>
> #include <vector>
> template<typename T>
> void printV(const std::vector<T>& v)
> {
>     if (v.size() == 1) {
>         printf("%d ", v[0]);
>         return;
>     }
>     int middle = v.size()/2;
>     printV(std::vector{v.begin(), v.end()+middle});
> }
> int main()
> {
>     std::vector<int> v = {10,1};
>     printV(v);
>     return 0;
> }
> 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. If the "printf" line is
> removed, no error is generated but clang will compile for what it looks
> like forever (the process is constantly at 100% and does not stop after
> several hours).
> This has been tested also with the following versions of clang: "Apple LLVM
> version 10.0.0 (clang-1000.10.44.4)", "clang version 7.0.1 (Fedora
> 7.0.1-6.fc29)". I also tested clang 8.0 and clang-HEAD on wandbox.org ,
> with the same results (on wandbox.org the process gets killed after a
> while).
> Obviously this only happens when compiling with "--std=c++17" or
> "--std=c++2a".
> Strangely enough, I got more or less the same results with gcc (7, 8.3 and
> HEAD), so my guess is that this might be related to some ambiguity either
> on the standard or in its interpretation. Given that as far as I know,
> clang and gcc are using two completely unrelated parsers and frontends.
> Using () instead of {} will properly give a syntax error. So my guess is
> that this is related to both CTAD and uniform initialization because of
> std::vector having an std::initializer_list constructor. At least form what
> I could understand from the huge error output, it looks like the compiler
> is recursively instantiating std::vector<T> with T =
> std::initializer_list<some iterator type>, but this may be wrong.
> If required I can provide part of the huge error output, but it can be
> generated by compiling the provided snippet on wandbox.
> Thanks to anyone who can sort this out!
> Best regards,
> Lorenzo

Very interesting find! You are correct that this happens due to infinite template recursion, not due to a bug in the standard. Consider:

template <typename> struct tag {};

template <typename T> void f(T a) { f(tag<T>{}); }

int main() { f(1); }

This also has infinite template recursion, but in that case, gcc and clang stop after a specified -ftemplate-depth. Seems like in your specific example this limit is somehow bypassed.

- Nicolas

More information about the cfe-dev mailing list