14

I am trying to initialize a constexpr declaration with a pointer to int which is a const object. I also try to define an object with a object that is not a const type.

Code:

#include <iostream>

int main()
{
constexpr int *np = nullptr; // np is a constant to int that points to null;
int j = 0;
constexpr int i = 42; // type of i is const int
constexpr const int *p = &i; // p is a constant pointer to the const int i;
constexpr int *p1 = &j; // p1 is a constant pointer to the int j; 
}

g++ log:

constexpr.cc:8:27: error: ‘& i’ is not a constant expression
constexpr.cc:9:22: error: ‘& j’ is not a constant expression

I believe it is because the objects in main have no fixed addresses, thus g++ is throwing error messages back at me; how would I correct this? Without using literal types.

TheBlueCat
  • 1,147
  • 5
  • 19
  • 38
  • Well, yeah. Variables only have addresses at runtime when they are assigned one. – chris Nov 21 '12 at 18:24
  • @chris Yes. How would I define a function to have its objects to have a fixed address? Would I just declare the function as constexpr? – TheBlueCat Nov 21 '12 at 18:27
  • @chris Can you explain your point more? The whole point of constexpr is that is defined at compiletime with mainly literal types (they're expections). My point is objects within functions have temporary addresses assigned to them (for obvious reasons). Here g++ is throwing me the error messages due to those temp memory addresses. How could I declare a function that would not do this (ie, allow all objects to be fixed during control of flow). – TheBlueCat Nov 21 '12 at 18:32
  • I highly doubt you can associate addresses or pointers to variables with `constexpr` at all. – chris Nov 21 '12 at 18:35
  • Note that literal types cannot be used here. – Jesse Good Nov 21 '12 at 22:07
  • @JesseGood How else are you supposed to enforce compile time evaluation? – TheBlueCat Nov 22 '12 at 15:51
  • @TheBlueCat: My point was you cannot take the address of a temporary object. A literal evaluates to a temporary, so cannot be used. Unless I misunderstood what you mean by `Without using literal types`. – Jesse Good Nov 22 '12 at 22:47
  • 1
    Unfortunately this example works fine in VS 2015. Poor Microsoft. – Lukáš Bednařík Nov 13 '15 at 08:12

1 Answers1

22

Make them static to fix their addresses:

int main()
{
  constexpr int *np = nullptr; // np is a constant to int that points to null;
  static int j = 0;
  static constexpr int i = 42; // type of i is const int
  constexpr const int *p = &i; // p is a constant pointer to the const int i;
  constexpr int *p1 = &j; // p1 is a constant pointer to the int j; 
}

This is known as an address constant expression [5.19p3]:

An address constant expression is a prvalue core constant expression of pointer type that evaluates to the address of an object with static storage duration, to the address of a function, or to a null pointer value, or a prvalue core constant expression of type std::nullptr_t.

Jesse Good
  • 50,901
  • 14
  • 124
  • 166
  • 1
    Isn't the address of a static variable defined at link-time, not at compile-time? – anton_rh Aug 08 '18 at 07:07
  • @anton_rh: Yes, the address is determined at link-time. That does not conflict with my answer above though. – Jesse Good Aug 08 '18 at 13:22
  • 2
    @JesseGood I think it's a good point to elaborate on, though. That a `constexpr` _can_ be a value resolved after compile time. – sh1 Jan 25 '21 at 04:32
  • If you look at the implementation then you see what actually happens is that the compiler will generate a constant + a linker reference how to fix up the constant relative to the link address. – Goswin von Brederlow Feb 12 '22 at 14:22