Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What more does using constexpr gives instead of just static const variables?

As I understand, calculation at compile time means, that at runtime instead of constexpr functions there will be const values (by definition, because they will be already calculated). That touches functions (they already calculated, so, it is just as variable of function type), that touches variables (it is just as static const variable), same with classes.

One plus from constexpr function I see: if in ANSI C, for example, I had to have 5 defines, maybe united logically, now I can write one such function and use it instead of 5 defines, being able to write logic to manipulate of set of constexpr function return values. So, as result I have same set of 5 values, but now I described them logically, writing such function.

But I feel I understand something wrong, because I see such examples:

class vec3 {
        union {
                struct {
                        float _x, _y, _z;
                };
                float _v[3];
        };

public:
        constexpr vec3(): _x(0), _y(0), _z(0) {} // 
        constexpr vec3(float x, float y, float z): _x(x), _y(y), _z(z) {}(1)
        constexpr vec3(const vec3&) = default; // (2)
        vec3 &operator=(const vec3&) = default; // (3)
        constexpr float x() { return _x; } // (4)
        constexpr float y() { return _y; }
        constexpr float z() { return _z; }
        constexpr const float *v() { return _v; } // (5)
        float *v() { return _v; }
};

(1) I can understand if constructor without parameters is constexpr. Yes, it is some const state that can be calculated at compile time and use in future, maybe faster. But why constructor with parameters? Object body will be on Stack or on Heap, we don't know which parameters we will put there, what for is it?

(2, 3) Same here, what for is it? How can we calculate at compile time copying of unknown object?

(4, 5) I wonder what for it can be used. Just for object which state was calculated at compile time? Or calling value of some object (that will be created at runtime) from Heap or Stack may costs much and that somehow will speed it on?

like image 967
Arkady Avatar asked Dec 09 '25 20:12

Arkady


1 Answers

You are missing the fact that the use of constexpr in member functions and constructors does not mean that they are always executed in compile-time. They are simply done so when possible.

A few examples for clarity:

  constexpr vec3 myGlobalVec{1,2,3}; // uses vec3(x,y,z) in compile time
  constexpr vec3 copyOfGlobalVec = myGlobalVec; // uses copy constructor in compile time

  void foo(int n) {
      vec3 my(n,n,n); // uses the same constructor, but invoked in runtime
      // ...
  }

The same applies to the remaining constructors: the key point is that with constexpr-qualified functions and constructors, if the full arguments list contains constant expressions (and if the object at hand is a constant expression), then the result will also be a constant expression.

The advantage of having constexpr getters is that attributes of constant expressions can be obtained for use in cases where only constant expressions are allowed. A float cannot be used as a template parameter, but assuming the vector was made of ints, you could do this:

  SomeClass<myGlobalVec.x()> anObject;
like image 113
E_net4 stands with Ukraine Avatar answered Dec 11 '25 10:12

E_net4 stands with Ukraine



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!