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。
我可以很容易地说,通过将函数声明为 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。