C++ 可变参数模板实例化深度超过最大值 900
c++ variadic template instantiation depth exceeds maximum of 900
我正在使用 c++11 可变参数模板,但是编译器抱怨模板实例化深度超过最大值 900,代码如下所示:
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...);
}
我正在使用这个模板:
auto composed_func = compose(f1, f2, f3, f4);
但是如果我将可变参数模板定义更改为:
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...);
}
它将正常工作。
我不清楚为什么会这样。在我看来,上面的用法看起来也有效,因为它仍然递归地减少 args 以调用 compose。
你的第二个函数有无限递归:它没有像你想象的那样调用第一个函数,而是调用它自己:
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...);
}
假设你打电话给:
compose(f, g, h);
这将使用 F1 = decltype(f)
、F2 = decltype(g)
和 Fs = {decltype(h)}
调用函数。该函数然后继续并调用:
compose(f1, f2)
实际上是:
compose(f, g);
这将使用 F1 = decltype(f)
、F2 = decltype(g)
和空 Fs = {}
调用相同的函数。基本执行:
compose(compose(f, g));
它再次用 F1 = decltype(f)
、F2 = decltype(g)
和一个空的 Fs = {}
调用自己。这一直持续到无穷大,或者直到达到 900 的限制。
你需要的是确保第二个函数只有在f2
:
之后才相关
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...);
}
您可以通过以下方式修复它:
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...);
}
ADL 可以找到不合格的名称,名称是在实例化时搜索的。
所以,通过不合格的查找,我们首先生成了候选人(即使他们不是更好的匹配)
compose(f, g)
可以是:
template<typename F1, typename F2> compose
- 或
template<typename F1, typename F2, typename...Fs> compose
。 (FS
空包)
对于后一种情况,我们有 decltype(compose(compose(f, g)))
需要解决,因此再次 compose(f, g)
-> 无限递归。
另一方面,立即搜索限定名称,并且只能找到完整声明的函数(因此不能找到它本身,因为结尾-return-类型是声明的一部分)。
所以 ::compose
避免将自己视为过载的候选对象。
我正在使用 c++11 可变参数模板,但是编译器抱怨模板实例化深度超过最大值 900,代码如下所示:
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...);
}
我正在使用这个模板:
auto composed_func = compose(f1, f2, f3, f4);
但是如果我将可变参数模板定义更改为:
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...);
}
它将正常工作。 我不清楚为什么会这样。在我看来,上面的用法看起来也有效,因为它仍然递归地减少 args 以调用 compose。
你的第二个函数有无限递归:它没有像你想象的那样调用第一个函数,而是调用它自己:
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...);
}
假设你打电话给:
compose(f, g, h);
这将使用 F1 = decltype(f)
、F2 = decltype(g)
和 Fs = {decltype(h)}
调用函数。该函数然后继续并调用:
compose(f1, f2)
实际上是:
compose(f, g);
这将使用 F1 = decltype(f)
、F2 = decltype(g)
和空 Fs = {}
调用相同的函数。基本执行:
compose(compose(f, g));
它再次用 F1 = decltype(f)
、F2 = decltype(g)
和一个空的 Fs = {}
调用自己。这一直持续到无穷大,或者直到达到 900 的限制。
你需要的是确保第二个函数只有在f2
:
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...);
}
您可以通过以下方式修复它:
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...);
}
ADL 可以找到不合格的名称,名称是在实例化时搜索的。
所以,通过不合格的查找,我们首先生成了候选人(即使他们不是更好的匹配)
compose(f, g)
可以是:
template<typename F1, typename F2> compose
- 或
template<typename F1, typename F2, typename...Fs> compose
。 (FS
空包)
对于后一种情况,我们有 decltype(compose(compose(f, g)))
需要解决,因此再次 compose(f, g)
-> 无限递归。
另一方面,立即搜索限定名称,并且只能找到完整声明的函数(因此不能找到它本身,因为结尾-return-类型是声明的一部分)。
所以 ::compose
避免将自己视为过载的候选对象。