模板实例化深度超过最大值 - 如何停止特定情况?

template instantiation depth exceeds maximum - how to stop particular case?

我有以下功能:

template<unsigned fromLine, unsigned toLine = fromLine>
void stateChanged()
{
    // onStateChangeHandler[fromLine]();

    if (fromLine < toLine)
        stateChanged<fromLine + 1, toLine>();
}

我这样称呼它:

stateChanged<0>();
stateChanged<1>();
stateChanged<2>();
stateChanged<3>();
stateChanged<4>();
stateChanged<5, 9>();
stateChanged<10, 15>();

我收到致命错误:模板实例化深度超过最大值 900。 我假设在 C++14 中 if 条件会自动停止它。那么,如何正确地做到这一点?

使用 if constexpr 而不是 if 将防止此代码无限循环

正如您现在编写的代码,stateChanged 的每个 实例化请求 stateChanged.

的不同实例化

before [编译器资源管理器]

after [编译器资源管理器]

template<unsigned fromLine, unsigned toLine = fromLine>
void stateChanged()
{
    // onStateChangeHandler[fromLine]();

    if constexpr(fromLine < toLine)
    {
        // If the above expression is false, this code is not compiled.
        stateChanged<fromLine + 1, toLine>();
    }
}

更新:

在 C++14 上,使用一些 SFINAE 可以产生相同的效果。

template<unsigned fromLine, unsigned toLine = fromLine,
         typename std::enable_if_t< fromLine>=toLine >* = nullptr >
void stateChanged()
{
    // onStateChangeHandler[fromLine]();
}

template<unsigned fromLine, unsigned toLine = fromLine,
         typename std::enable_if_t< fromLine<toLine >* = nullptr >
void stateChanged()
{
    // onStateChangeHandler[fromLine]();

    stateChanged<fromLine + 1, toLine>();
}

C++14 after [编译器资源管理器]

无法在模板定义中使用 if constexpr,您需要更改循环方式,以便为编译器引入一种方法来达到终止状态并停止模板实例化。

我们可以使用助手 class 来完成此操作,而不是从头到尾处理多行。

template <unsigned curLine, unsigned numLines>
void updateStateChanged()
{
    // onStateChangeHandler[curLine]();
    stateChanged<curLine + 1, numLines - 1>();
}

template <unsigned curLine>
void updateStateChanged<curLine, 0>()
{
    // onStateChangeHandler[curLine]();
}

// Then we can modify your original class to call this helper:

template<unsigned fromLine, unsigned toLine = fromLine>
void stateChanged()
{
    updateStateChanged(fromLine, toLine - fromLine);
}