据我了解this proposal C++20 取消了对在 constexpr 上下文中使用虚函数的限制。更改本身很简单,删除了“它不应是虚拟的”字样。这样做的理由似乎是无论如何都必须知道所有的动态类型,因此允许它的成本几乎为零。
引起我兴趣的是关于协方差的讨论。论文末尾给出了一个例子:
struct X1 { constexpr virtual X1 const* f() const { return this; } }; struct Y { int m = 0; }; struct X2: public Y, public X1 { constexpr virtual X2 const* f() const { return this; } }; constexpr X1 x1; static_assert( x1.f() == &x1 ); constexpr X2 x2; constexpr X1 const& r2 = x2; static_assert( r2.f() == &r2 );
根据我的阅读,decltype(r2.f())
可能是 X2 const*
而不是 X1 const*
。毕竟,如果动态类型是完全已知的,那不是最简单的实现吗?
所以在上面的例子中我应该期望它编译:
constexpr decltype(r2.f()) zz = &x1;
(FWIW 在线可用的编译器版本 seem to accept it,这不是我预期的。我问是因为如果这确实按照我预期的方式工作,那么它将允许使用类型玩一些非常时髦的游戏编译时的删除样式技术)。
最佳答案
After all, if the dynamic type is completely known isn't that the simplest implementation?
仅仅因为代码在编译时被调用并不意味着 C++ 的正常规则被暂停。如果表达式的类型在非编译时代码中是一回事,那么如果该代码在编译时运行,它将是相同的。
在运行时,运行时环境(无论是否在编译时执行)知道所有指向对象的指针/引用的动态类型。毕竟,如果不这样做,dynamic_cast
将无法工作。但这并没有改变这样一个事实,即调用基类函数将返回是基类函数说它返回,而不管您碰巧传递的是什么动态类型。
FWIW the versions of compilers available online seem to accept it, which isn't what I anticipated.
接受是因为&x1
是X1*
类型,decltype
表达式是X1*
类型>。所以你只是在复制一个 X1*
。
关于c++ - 虚拟 constexpr 协变返回类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57470885/