代码之家  ›  专栏  ›  技术社区  ›  Wad

斐波那契和“if constexpr”

  •  2
  • Wad  · 技术社区  · 7 年前

    请考虑以下代码:

    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 回复  |  直到 7 年前
        1
  •  7
  •   Nicol Bolas    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,则最终返回语句中的代码不会导致实例化模板。