0
点赞
收藏
分享

微信扫一扫

constexpr关键字

芷兮离离 2022-02-09 阅读 90
c++constexpr

constexpr关键字

起因

cppreference.com上查看std::find_if函数的签名如下:
在这里插入图片描述

c++20前函数没有constexpr修饰,c++20及以后使用constexpr进行修饰,为什么?
c++20后添加constexpr对之前的代码会有影响吗(会不会导致之前的代码失效)?
下面来一一解答这些问题?

c++20为什么使用constexpr修饰find_if

C++20 library features中有描述该特性:
在这里插入图片描述
c++20 library为 和 添加了constexpr支持。
主要是为了解决(具体细节见papers P0202R3 ):

#include <array>
#include <algorithm>
 
int main() {
        // OK
        constexpr std::array<char, 6> a { 'H', 'e', 'l', 'l', 'o' };

        // Failures:
        // * std::find is not constexpr
        constexpr auto it = std::find(a.rbegin(), a.rend(), 'H');
}

c++20后添加constexpr对之前的代码会有影响吗(会不会导致之前的代码失效)?

按照P0202R3的介绍不会有任何影响,单纯的库扩展。

这个是结论,如何实现的呢?首先我们从constexpr的作用说起:
Constexpr 起源(c++11)
Constexpr 在c++11中引入的:
在这里插入图片描述
详细的Paper见N2235;
概括的来讲主要是解决如下问题:

  • 让编译期计算达到类型安全
  • 一般来说,通过将计算移至编译期来提高效率
  • 支持嵌入式系统编程(尤其是 ROM)
  • 直接支持元编程
  • 让编译期编程与“普通编程”非常相似

对于Constant-expression functions值得注意的一点描述有:一个constexpr function是可能被使用non-constant expressions调用的,这个时候这个函数调用就不需要编译器计算。

constexpr int func(int x)
{ return x; }

int main() {
    constexpr int i = 1;
    func(i); // 编译期计算
    int j = 2;
    func(j); // 运行期计算
    return 0;
}

这也正可以解释一个函数从没有constexpr到添加constexpr关键字,是不会对原来的代码有影响的(使用no-constant expression调用时,constexpr相当于退化掉了)。
c++11,一些constexpr function例子(fine是合法,error是不合法):

// square可以解决宏函数的一些问题:类型不安全问题
constexpr int square(int x)
{ return x * x; } // fine

constexpr long long_max() { return 2147483647; } // fine 

constexpr int abs(int x) { return x < 0 ? -x : x; } // fine 

constexpr void f(int x) // error: return type is void 
{ /* ... */ } 

constexpr int next(int x) 
{ return ++x; } // error: use of increment 

constexpr int g(int n) // error: body not just ‘‘return expr’’ 
{ 
    int r = n;
    while (--n > 1) r *= n;
    return r;
}

constexpr int twice(int x);
enum { bufsz = twice(256) }; // error: twice() isn’t (yet) defined 

constexpr int fac(int x)
{ return x > 2 ? x * fac(x - 1) : 1; } // error: fac() not defined before use

c++14对constexpr的扩充:
C++14 允许在 constexpr 函数中使用局部变量,从而支持了循环;

#include <iostream>
constexpr int test(int n) {
    int k = n; // 支持局部变量
    k++;
    return k; 
}

int main() {
    constexpr int i = 11;
    int k = test(i); // 编译期计算
    int j = 22;
    int m = test(j); // 运行期计算
}

这种放松简化了许多 constexpr 函数并使许多 C++ 程序员感到高兴。他们不满地发现,以前在编译时只能对算法的纯函数表达式进行求值。特别是,他们希望使用循环来避免递归。就更长期来看,这释放出了要在 C++17 和 C++20中进一步放松限制的需求。为了说明潜在的编译期求值的能力,我已经指出 constexpr thread 也是可能的,尽管我并不急于对此进行提案。

举报

相关推荐

0 条评论