Search code examples
c++constantsc++20

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

  • 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