'How to call an operator with constexpr without using temporary variables?
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?
Solution 1:[1]
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;
}
Solution 2:[2]
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.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 |
