Question

If an object is declared const, its value is guaranteed to be available only at runtime, but if it's declared constexpr, the value is guaranteed to be available both during compilation and at runtime. So if I have an object whose value is available during compilation, are there any situations where I should not declare it constexpr?

const int magicValue = 42;      // Does this ever make sense
                                // (using const instead of constexpr)?

For functions, if a function can return a value computed during compilation when passed arguments with values available during compilation, would it ever make sense to not declare the function constexpr?

struct Point { int x; int y; };

Point midPoint(Point p1, Point p2)                       // Does this ever make
{                                                        // sense (not declaring
    return { (p1.x + p2.x) / 2 , (p1.y + p2.y) / 2 };    // the function
}                                                        // constexpr)?

The only case I can conceive of is when you don't want to commit to the function being able to compute a compile-time constant when called with known-at-compile-time arguments, e.g., if you want to preserve the flexibility to change midPoint's implementation without changing its interface (thus potentially breaking callers). For example, you might want to preserve the flexibility to add non-constexpr side-effects to midPoint, e.g., IO.

Was it helpful?

Solution

For variables, I don't see any reason not to use constexpr when you can. But it's not always possible to do so, e.g. when the initializer of a variable is computed by a virtual function e.g.

Adding constexpr to a function is an interface change: you are expressing the fact that you can use it to initialize constexpr variables. This imposes constraints on the implementation of your function, such as no calling of virtual functions, no dynamic memory allocations and no lambda functions as function objects.

Note that the resolution to LWG issue 2013 does not allow implementers of the Standard Library the freedom to add constexpr to library functions. One of the reasons is that declaring a function constexpr can inhibit certain debugging implementations that do dynamic allocations (notably iterator checking). This means that future expansions of constexpr to the Standard Library need to be separate proposals. This is in contrast to noexcept, where library writers have more freedom.

OTHER TIPS

You can change a const:

int const x = 1;

*const_cast<int *>(&x) = 5;

You cannot do the same with constexpr, which allows the compiler to know without a doubt that the expression is available at compile time, and thus optimizations are possible.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top