Fibonacci和' if constexpr'

时间:2017-12-23 18:58:11

标签: c++ templates if-statement c++17 constexpr

请考虑以下代码:

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;
}

当我在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

这不是我所期望的;我希望结果是2.我在这里错误地使用了if constexpr吗?

此外,我不了解编译器的诊断信息。

Fib(3) = Fib(2)              + Fib(1)
       = Fib(1) + Fib(0)
       = 1      + 0          + 1
       = 2

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

1 个答案:

答案 0 :(得分: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>();
}

如果nIndex为0或1,则最终return语句中的代码不会导致模板被实例化。