I've been thinking why constexr
and virtual
are mutually exclusive, and someone added:
... constexpr is all about execution at compile time; if we're executing the function at compile time, we obviously know the type of data upon which it's acting at compile time as well, so late binding clearly isn't relevant.
However, it's possible that the dynamic type is not identical to the static type even in compile-time, and there might be cases where the dynamic type is needed:
class A {
public:
/* virtual */ constexpr int foo() {
return 1;
}
};
class B : public A {
public:
constexpr int foo() {
return 2;
}
};
constexpr int foo(A &a) {
// The static type is fixed here.
// What if we want to call B::foo() ?
return a.foo();
}
int main() {
B b;
constexpr int c = foo(b);
return 0;
}
That is, my question is
Can virtual functions be constexpr? Yes. Only since C++20, virtual functions can be constexpr .
constexpr indicates that the value, or return value, is constant and, where possible, is computed at compile time. A constexpr integral value can be used wherever a const integer is required, such as in template arguments and array declarations.
In Conclusion. constexpr is an effective tool for ensuring compile-time evaluation of function calls, objects and variables. Compile-time evaluation of expressions often leads to more efficient code and enables the compiler to store the result in the system's ROM.
Yes. I believe putting such const ness is always a good practice wherever you can. For example in your class if a given method is not modifying any member then you always tend to put a const keyword in the end.
This restriction exists since constexpr
was introduced in C++11:
10.1.5 The
constexpr
specifier [dcl.constexpr]3 The definition of a constexpr function shall satisfy the following requirements:
(3.1) - it shall not be virtual;
The fact is, it may just be an oversight. Since in a constant expression the dynamic type of the object is required to be known, this restriction is unnecessary and artificial: This is what Peter Dimov and Vassil Vassilev assert in P1064R0, where they propose to remove it.
In fact, the wording for it no longer exists in the current draft.
Because virtual calls are resolved via vtables/RTTI (RunTime Type Information) located in the memory layout of your object at runtime, the "true type" behind the "used object handle" is not known at compile time.
In your example:
constexpr int foo(A &a) {
// The static type is fixed here.
// What if we want to call B::foo() ?
return a.foo();
}
If the foo
member function is virtual there is no way for that foo function to be executed at compile time. And there is no point in marking a function as constexpr
if it can never be executed at compile time. Hence there is no point in ever marking something both constexpr
and virtual
.
Now technically, depending on the code complexity, multiple cases might be resolvable by adding a completely new system (other than RTTI) to resolve virtual calls that would be compile time compatible (e.g some form of compiler meta data when everything is constexpr
that remembers what type of instance you put in a pointer/reference) but that simply is not a thing right now.
If you want a runtime indirection (which is what virtual
does) it doesn't make much sense to also want that to be executed at compile time.
P.S: sorry for the "compile time" and "runtime" spam.
Indeed, it is possible for compilers to know at compile time what is the dynamic type of a constant expression. This is a possibility, that is some time used by optimizer to devirtualize calls at compile time.
But the c++ language evolution take also in consideration how difficult it is to implement it in compilers. If such a consideration were not taken, then the c++ standard will be too far from the c++ coded so that it would be unusefull.
Maybe, it has been evaluated that keeping trac of the static type of every reference during constant expression evaluation would be too expensive to implement. This is where reality hurts!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With