首页 > 编程笔记 > C++笔记 阅读:14

C++ consteval用法详解(附带实例)

C++ 中,如果函数的所有输入在编译时可用,那么 constexpr 函数允许在编译时进行函数运算。然而,这不是一定的,constexpr 函数也可能在运行时执行。

consteval 是 C++20 中引入的一个关键字,用于强制函数在编译期间计算,确保函数在编译时产生常量表达式

C++ consteval的使用方式

使用 consteval 关键字,当你想要:
1) 定义必须在编译时运算的非成员函数或函数模板:
constexpr unsigned int factorial(unsigned int const n)
{
    return n > 1 ? n * factorial(n-1) : 1;
}

2) 定义必须在编译时执行的用来初始化 constexpr 对象的构造函数及只在编译时调用的成员函数:
class point3d
{
    double x_;
    double y_;
    double z_;
public:
    constexpr point3d(double const x = 0,
                      double const y = 0,
                      double const z = 0)
        : x_{x}, y_{y}, z_{z}
    {}

    constexpr double get_x() const {return x_;}
    constexpr double get_y() const {return y_;}
    constexpr double get_z() const {return z_;}
};

深度剖析C++ consteval

consteval 说明符在 C++20 中引入。它只可用于函数或函数模板,并定义它们为即时函数。这意味着任何函数调用必须在编译时执行,并产生编译时常量表达式。如果函数不能在编译时进行运算,那么程序格式错误,编译器会报编译错误。

即时函数有以下规则:
如何使用 factorial() 函数如下所示:
constexpr unsigned int f = factorial(6);
std::cout << f << '\n';

constexpr point3d p {0, 1, 2};
std::cout << p.get_x() << ' ' << p.get_y() << ' ' << p.get_z() << '\n';

然而,以下示例会产生编译错误,因为即时函数 factorial() 和 point3d 的构造函数无法在编译时进行运算:
unsigned int n;
std::cin >> n;
const unsigned int f2 = factorial(n); // error

double x = 0, y = 1, z = 2;
constexpr point3d p2 {x, y, z}; // error

除非即时函数在常量表达式里,否则无法对其取地址:
using pfact = unsigned int(unsigned int);
pfact* pf = factorial;
constexpr unsigned int f3 = pf(42); // error

constexpr auto addr_factorial()
{
    return &factorial;
}

constexpr unsigned int invoke_factorial(unsigned int const n)
{
    return addr_factorial()(n);
}

constexpr auto ptr = addr_factorial(); // ERROR: cannot take the pointer of an immediate function
constexpr unsigned int f2 = invoke_factorial(5); // OK
因为即时函数在运行时不可见,它们的符号没有生成,因此调试器无法显示它们。

相关文章