Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c++ variadic template instantiation depth exceeds maximum of 900

I am using c++11 variadic template, however the compiler complains template instantiation depth excedds maximun of 900, the code looks like:

template<typename F1, typename F2>
composed<F1, F2> compose(F1 f1, F2 f2) {
    return composed<F1, F2>(f1, f2);
}
template<typename F1, typename F2, typename... Fs>
auto compose(F1 f1, F2 f2, Fs... fs) ->decltype(compose(compose(f1, f2), fs...)) {
    return compose(compose(f1, f2), fs...);
}

I am using this template like:

auto composed_func = compose(f1, f2, f3, f4);

But if I change the variadic template defination to:

template<typename F1, typename F2, typename F3, typename... Fs>
auto compose(F1 f1, F2 f2, F3 f3, Fs... fs) ->decltype(compose(compose(f1, f2), f3, fs...)) {
    return compose(compose(f1, f2), f3, fs...);
}

It will work OK. I am not clear why this happened. It seems to me that the upper usage also looks valid since it still recursively reduce the args to call compose.

like image 713
D.pz Avatar asked Sep 06 '18 03:09

D.pz


1 Answers

You might fix it with:

template<typename F1, typename F2>
composed<F1, F2> compose(F1 f1, F2 f2) {
    return composed<F1, F2>(f1, f2);
}

template<typename F1, typename F2, typename... Fs>
auto compose(F1 f1, F2 f2, Fs... fs)
->decltype(compose(::compose(f1, f2), fs...))
{
    return compose(compose(f1, f2), fs...);
}

Demo

Unqualified names can be found by ADL and name is search at the point of instantiation.

so, with unqualified look up, we first generated the candidates (even if they won't be the better match)

compose(f, g) can be:

  • template<typename F1, typename F2> compose
  • or template<typename F1, typename F2, typename...Fs> compose. (with FS empty pack)

for the later case, we have decltype(compose(compose(f, g))) to resolve, and so compose(f, g) again -> infinite recursion.

On the other part, qualified names is search immediately, and only fully declared functions can be found (so not itself, as the trailing-return-type is part of the declaration). so ::compose avoid to consider itself as candidate of overloads.

like image 101
Jarod42 Avatar answered Sep 22 '22 15:09

Jarod42