这是我的简化测试代码:
struct Test {
Test() { run(0); }
template<class T>
static auto run(T&&, bool stop = false) -> void { if (!stop) _run<T>(); }
template<class R>
static auto _run() -> void { [] () { run([] () {}, true); }(); }
};
当我使用GCC和clang编译此代码时,它会出现编译错误:
/media/data/caca3d/src/b0util/test/tst_promise.cpp:30: error: template instantiation depth exceeds maximum of 900 (use -ftemplate-depth= to increase the maximum)
static auto _run() -> void { [] () { run([] () {}, true); }(); }
~~~^~~~~~~~~~~~~~~~
我无法理解为什么这段代码会导致无限的模板实例化。
仅供参考,如果我删除template<class R>
函数中的_run()
,错误就会消失。
我在使用lambda函数尝试一些惰性求值时发现了这个错误,所以我无法删除lambda中的间接调用。 我该如何解决这个问题?
答案 0 :(得分:1)
让我们仔细看看发生了什么。第一个函数显式调用_run()
的模板化版本,我想你对此部分没有任何疑问。
template<class T>
static auto run(T&&, bool stop = false) -> void { if (!stop) _run<T>(); }
第二个更有趣。它似乎只会被实例化一次(因为你只是用lambda调用run()
一次),但是根据标准,每个lambda都有它自己的唯一类型,所以每次{ {1}}被实例化它将强制创建新版本的_run()
(因为run()
是从函数的参数类型推导出来的,创建了一个无限循环。
T
在这个特定示例中解决此问题的最简单方法是使template<class R>
static auto _run() -> void { [] () { run([] () {}, true); }(); }
获取与您的lambda匹配的特定(可能是模板参数)类型的run()
。