Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

constexpr member functions gives C2131

I’ve understood the differences between const and constexpr and their applications, but I can’t get it’s the following error:

// .hpp file
class MyClass {
public:
    constexpr double Square(double toBeSquared);
    static constexpr double Cube(double x);
    double ProcessRoutine();
};

// .cpp file
constexpr double alternative_square_routine(double x)
{
    return x * x;
}

double MyClass::Square(double toBeSquared)
{
    return x * x;
}

double MyClass::Cube(double x)
{
    return x * x * x;
}

double MyClass::ProcessRoutine()
{
    // C2131: expression did not evaluate to a constant
    constexpr double square_const = Square(10.0);
    // This is fine:
    const double another_square = Square(5.0);
    // This is also fine:
    constexpr double another_square_again = alternative_square_routine(5.0);
    // Even this is fine:
    constexpr double cube = Cube(3.0);
}

MSVC informs me that it’s something involving the this pointer, while trying the code in Codiva.io (I guess it uses GCC) gives this output:

error: constexpr variable 'square_const' must be initialized by a constant expression

Where’s the problem?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

const just means that the variable, once initialized, should not be modifiable. The initialization will happen as normal for any other variable at runtime.

constexpr is much stronger and additionally enforces that the initialization is a constant expression, i.e. that it can be evaluated at compile-time when compiling the declaration, so that the compiler can replace the initialization with just the resulting value.

The rules for what expression qualifies as constant expression are very specific and can be found e.g. here at cppreference.

Before P2280 this could only be evaluated in a constant expression evaluation if it is used inside a constexpr function being evaluated as part of the constant expression.

constexpr double square_const = Square(10.0);

is short for

constexpr double square_const = this->Square(10.0);

because Square is a non-static member function. And here you are evaluating this as part of the initialization of square_const which you want to be a constant expression (because of constexpr), while not in a constexpr function being evaluated as part of that constant expression evaluation.

P2280 has been accepted for C++23 and as defect report against C++11 to C++20. With it, using this here would be allowed as long as you don’t try to access the value of *this. Since this is a recent defect report, compilers probably don’t implement it yet. The cppreference link above isn’t updated for it yet.

With just const instead of constexpr there is no requirement for any constant expression evaluation, so there is no reason for it to fail.

alternative_square_routine and Cube are fine, because there is no this involved. These are not non-static member functions.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading