斐波那契和'if constexpr'

Wad*_*Wad 2 c++ templates if-statement constexpr c++17

请考虑以下代码:

template<int nIndex>
int Fibonacci()
{
    if constexpr (nIndex == 0) return 0;
    if constexpr (nIndex == 1) return 1;

    static_assert(nIndex >= 0, "Invalid index passed to Fibonacci()");
    return Fibonacci<nIndex - 1>() + Fibonacci<nIndex - 2>();
}

int main()
{
    Fibonacci<3>(); // 2
    //Fibonacci<-1>();  // Fires assertion 

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

当我在VS2017中运行它时,编译器输出:

error C2338: Invalid index passed to Fibonacci()
note: see reference to function template instantiation 'int Fibonacci<-1>(void)' being compiled
note: see reference to function template instantiation 'int Fibonacci<1>(void)' being compiled
note: see reference to function template instantiation 'int Fibonacci<3>(void)' being compiled
Run Code Online (Sandbox Code Playgroud)

这不是我的期望; 我希望结果是2.我if constexpr在这里使用不正确吗?

此外,我不理解编译器的诊断消息.

Fib(3) = Fib(2)              + Fib(1)
       = Fib(1) + Fib(0)
       = 1      + 0          + 1
       = 2
Run Code Online (Sandbox Code Playgroud)

那么编译器为什么认为Fib(-1)被调用呢?

Nic*_*las 7

那么编译器为什么认为Fib(-1)被调用呢?

它没有; 它认为它已经被实例化(或者更具体地说,Fibonacci<-1>已经被实例化).

你想要的是条件实例化.只有实例化模板的if constexpr语句本身由语句管理时才能实现这一点:

template<int nIndex>
int Fibonacci()
{
    static_assert(nIndex >= 0, "Invalid index passed to Fibonacci()");

    if constexpr (nIndex == 0) return 0;
    else if constexpr (nIndex == 1) return 1;
    else
      return Fibonacci<nIndex - 1>() + Fibonacci<nIndex - 2>();
}
Run Code Online (Sandbox Code Playgroud)

如果nIndex是0或1,那么最终return语句中的代码将不会导致模板被实例化.

  • @Wad:不,这不是关于什么被执行.这是关于*实例化*的内容.你继续输入`Fib(1)`,当实际发生的是`Fibonacci <1>()`.那些不是一回事.后者是模板实例化.如果语句`Fibonacci <-1>`出现在程序*的任何地方*,那么由于静态断言,程序将无法编译. (3认同)