C++20 中 constexpr 虚函数的优点是什么?

What is the advantage of constexpr virtual functions in C++20?

我可以很容易地说,通过将函数声明为 constexpr,我们在编译时对其进行评估,这在 运行 期间节省了时间,因为结果已经产生。

另一方面,虚函数需要在运行时间内解决。因此,我想我们不能摆脱解决过程。由于constexpr函数的机制,只有结果可以快速获取。

constexpr virtual 函数还有其他好处吗?

显而易见的好处是,您现在甚至可以在编译时调用虚函数。

struct Base {
    constexpr virtual int get() { return 1; }
    virtual ~Base() = default;
};

struct Child : Base {
    constexpr int get() override { return 2; }
};

constexpr int foo(bool b) {
    Base* ptr = b ? new Base() : new Child();
    auto res = ptr->get(); // this call is not possible prior to C++20
    delete ptr;

    return res;
}

constexpr auto BaseVal = foo(true);
constexpr auto ChildVal = foo(false);

您不能在 C++20 之前的常量表达式中通过基指针使用 get 函数。如果你做到了constexpr,你就可以。 Example.


现在想想我们可以在编译时从虚函数调用中获得什么好处:也许是编译时间。 C++基本上有两种机制来处理多态性:

  • 模板,以及
  • 虚函数。

两者解决的问题本质上是相同的,但在程序生命周期的不同阶段。当然,在编译时进行尽可能多的计算并因此在 运行 时具有最佳性能是很好的。但是,这并不总是一种可行的方法,因为由于模板的工作方式,编译时间可能会迅速增加。

猜测从这里开始。现在,如果我们拓宽可以调用虚函数的阶段并允许在编译时调用它们呢?在某些情况下,这将允许我们用虚函数调用替换大量递归或嵌套的模板。假设 constexpr 解释器比编译器递归解析模板更快,您可以看到一些编译时间减少。

当然,这种好处会被概念和模块带来的性能提升所掩盖。


另一个好处在于 constexpr 的一般性质:在不断评估期间禁止 UB。这意味着您可以使用一些静态断言检查您的虚函数是否没有 UB。