【问题标题】:How to understand constexpr in this example?在这个例子中如何理解 constexpr?
【发布时间】:2019-08-23 13:14:04
【问题描述】:

我试图理解 constexpr 应用于函数时的含义。在下面的示例中,程序编译并运行,但我不明白如何在编译时推导出函数 sum(int n),因为直到运行时才知道 n。我正在使用带有最新更新的 VS 2017。

无论是否包含 constexpr,程序都会编译。

#include <iostream>

constexpr int sum(int n)
{    
    return (n <= 0) ? 0 : n + sum(n-1);
}

int main()
{
    int i;
    std::cin >> i;
    std::cout << sum(i) << std::endl;

    return 0;
}

我预计编译器会出错 sum(int n) 不是常量表达式。还是 constepxr 只是对编译器的提示,例如“内联”,可以随意忽略?

【问题讨论】:

    标签: c++ c++17


    【解决方案1】:

    我预计编译器会出错 sum(int n) 不是常量表达式。

    constexpr int sum(int n); 表示函数可以在编译时进行评估。它不一定是。您可以在运行时调用它而不会出现任何问题,这样可以避免程序员在运行时和编译时需要相同功能时重复代码。

    使用 C++20,您可以通过使用新关键字 consteval 而不是 constexpr 限定函数来触发您所期望的错误。

    consteval int sum(int n)
    {
        // As before...
    }
    
    int i;
    
    // determine i at runtime...
    
    sum(i); // Error! Not evaluated at compile time.
    

    您可以查看P1073 了解此功能。该提案已被批准用于下一个标准。

    【讨论】:

      【解决方案2】:

      constexpr 关键字表示函数必须在编译时进行评估,如果它在 constexpr 上下文中调用

      考虑:

      constexpr int sum(int n)
      {    
          return (n <= 0) ? 0 : n + sum(n-1);
      }
      
      int main()
      {
          int i;
          std::cin >> i;
      
          constexpr int s1 = sum(4);        // OK, evaluated at compile time
          int s2 = sum(i);                  // OK, evaluated at run time
          constexpr int s3 = sum(i);        // Error, i cannot be evaluated at compile time
          int s4 = sum(4);                  // OK, execution time depends on the compiler's mood
      }
      

      这里,s3constexpr,因此它的初始化程序需要在编译时进行评估。因此出现错误。
      如果没有此功能,您将不得不编写两个版本的函数,一个用于编译时使用,另一个用于运行时使用。
      Compiler Explorer 上亲自查看。

      另请注意,constexpr 暗含函数的 inline

      【讨论】:

      • 现在说得通了,感谢 Compile Explorer 链接!
      【解决方案3】:

      这是我的观点

      constexpr, ensures that the constant must be a compile-time constant
      

      这样

      constexpr double pi (3.5); // is Okay because resolution is at compile time
      

      还有这个

      // Should be Okay be cause the resolution of **sum** is at compiletime
      // evaluation however is run-time dependent
      constexpr int sum(int n)
      {
          return (n <= 0) ? 0 : n + sum(n-1);
      }
      

      另一个例子是这样的

      constexpr int compute(int x) { 
        return x+1; 
      } 
      
      int foo[compute(15)];    
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-12-07
        • 1970-01-01
        • 2012-11-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-08-17
        相关资源
        最近更新 更多