无限模板实例化

时间:2017-02-03 06:29:46

标签: c++ templates lambda

这是我的简化测试代码:

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中的间接调用。 我该如何解决这个问题?

1 个答案:

答案 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()