The following sample code illustrates my problem.
constexpr int fact(int N) {
return N ? N * fact(N - 1) : 1;
}
struct A {
int d;
constexpr A operator (const A& other) const { return A{ fact(d other.d) }; }
// overload of many other operators
};
int main() {
int x;
cin >> x; // run time argument
constexpr A a{ 2 }, b{ 3 };
A c{ x };
A u = a b c; // both eval at run time
//constexpr A v = a b c; // doesn't compile because c is not constant
}
What I want to achieve is that the first operator
is evaluated at compile time and the second operator
is evaluated at run time.
It is of course possible to break it into
constexpr A tmp = a b;
A u = tmp c;
but in my case the whole point of overloading operators is to allow building more complicated formulas in a more intuitive way, so that would make the overloading pointless.
If I declare operator
as consteval
, then it again doesn't compile. And I cannot overload it twice.
Is there a solution?
CodePudding user response:
You can force the evaluation with (non-type) template parameter or consteval
function.
constexpr int fact(int N) {
return N ? N * fact(N - 1) : 1;
}
struct A {
int d;
constexpr A operator (const A& other) const { return A{ fact(d other.d) }; }
};
consteval auto value(auto v){return v;}
A foo (int x) {
constexpr A a{ 2 }, b{ 3 };
A c{ x };
A u = value(a b) c;
return u;
}
https://godbolt.org/z/ohf61vebv
CodePudding user response:
No, at least in gcc and with optimization, here you can see it evaluate at compile time. (the 120
)
main:
mov eax, 1
add edi, 120
je .L4
.L3:
imul eax, edi
sub edi, 1
jne .L3
ret
.L4:
ret
*To be fair even without constexpr
compiler would probably also optimize it.