使用consteval代替constexpr函数有什么好处?

问题描述

我知道需求的不同,我最感兴趣的是代码质量带来的好处。

我能想到的几件事:

  • 阅读器仅读取函数签名并知道在编译时对函数进行了评估
  • 由于consteval fns在运行时从未使用过,因此编译器发出的代码可能更少(这是推测性的,我对此没有实际数据)
  • 不需要变量来强制ctfe,例如结尾

注意:如果代码质量太模糊,我理解某些人可能想结束这个问题,对我来说,代码质量并不是那个模糊的术语,而是...

example,其中constexpr故障延迟到运行时:

constexpr int div_cx(int a,int b)
{ 
  assert(b!=0);
  return a/b;
}
    
int main()
{
    static constexpr int result = div_cx(5,0); // compile time error,div by 0
    std::cout << result; 
    std::cout << div_cx(5,0) ; // runtime error :( 
}

解决方法

为了具有有意义的,显着的静态反射(在编译时进行反射),您需要一种在编译时执行代码的方法。最初的静态反射TS提案使用了传统的模板元编程技术,因为它们是在编译时执行代码的唯一有效工具。

但是,随着constexpr代码获得更多功能,通过constexpr函数进行编译时静态反射变得越来越可行。这种想法的一个问题是,不能允许静态反射值泄漏到非编译时代码中。

我们需要能够编写只能在编译时执行的代码。对于函数中间的少量代码,这样做很容易。该代码的运行时版本根本不包含反射部分,而只包含它们的结果。

但是,如果您要编写一个接受反射值并返回反射值的函数,该怎么办?还是反射值列表?

该函数不能为constexpr,因为constexpr函数必须能够在运行时执行。允许您执行诸如获取指向constexpr函数的指针之类的操作,并以编译器无法跟踪的方式调用它们,从而迫使其在运行时执行。

具有反射值的函数无法做到这一点。它必须仅在编译时执行。因此constexpr不适合此类功能。

输入consteval:一个"required" to execute only at compile time的函数。有一些特定的规则使指向这些函数的指针无法泄漏到运行时代码等中。

正因为如此,consteval目前没有太多目的。它在a few places like source_location::current(),中使用,从根本上讲,在运行时执行没有意义。但最终,该功能是进一步的尚不存在的编译时编程工具的必要构建块。

这是在paper that originally proposed this feature中规定的:

然而,本文的推动力是SG7在编译时反射领域中所做的工作。现在,人们普遍同意,将来对反射的语言支持应该使用constexpr函数,但是由于“反射函数”通常必须在编译时进行评估,因此它们实际上很可能是立即函数。