跳至正文

constexpr, consteval, constinit家族

  • 技术

介绍

这是《现代C++语言核心特性解析》的读书笔记。

constexpr家族的内容

书里给constexpr给了很多篇幅,但是总体来说就是一个,const表示的是不允许修改的常量,而constexpr表示的是编译期的常量。
但是逐渐被扩展到constexpr可以被用作函数,lambda,以及if constexprt,都是为了让编译期可以做更多的事情,给与开发者更多的自主性。
反正基本上想要去做一些预计算以及在模板里,用constexpr就没错了。

consteval是什么呢?

这件事情我理解来说就是constexpr被扩展定义之后的一个收缩,constexpr最初是为了定义编译期的常量,好让编译器在编译器做一些逻辑。但是逐渐扩展到函数也能放,同时运行期也能调用constexpr的函数。
那consteval做的事情就是,定义一个函数,这个函数只允许编译期运行。

说实话,有点过渡定义……

constinit的构造

因为之前做一个东西遇到过类似的依赖问题,后来用了宏+一个很取巧的类构造的方式来保证顺序。
然后C++20提供了一个更简单的方法,constinit保证在编译期就会初始化对象,相当于是最早初始化的一批对象。

  1. 编译期的计算都可以在编译期算好,就不会有启动的依赖关系;
  2. 可以被其他的非constinit对象依赖。

is_constant_evaluated

新标准还提供了一个新函数,用于区分当前逻辑运行在编译期还是运行时,可以用if constexpr去做不同的逻辑。

#include <cmath>
#include <type_traits>
constexpr double power(double b, int x) {
  if (std::is_constant_evaluated() && x >= 0) {
    double r = 1.0, p = b;
    unsigned u = (unsigned)x;
    while (u != 0) {
      if (u & 1) r *= p;
      u /= 2;
      p *= p;
    }
    return r;
  } else {
    return std::pow(b, (double)x);
  }
}

int main() 
{
  constexpr double kilo = power(10.0, 3);  // 常量求值
  int n = 3;
  double mucho = power(10.0, n);           // 非常量求值
  return 0;
}
标签:

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

目录