Reputation: 5850
I have a variable whose address is passed as the fourth parameter to setsocketopt. Notice that this parameter is declared as a constant pointer (const void *optval
).
In a patch I put up for review I changed the declaration of that variable to static constexpr. A reviewer of this change had concerns: he felt that it was questionable whether you can always take the address of a constexpr. He suggests that I make it const. I couldn't find much about addresses of constexpr variables and concerns about it after googling around. Can someone explain what the guarantees are concerning the address of a constexpr variable and what the caveats are about using it (if any)?
In case it's helpful, here's the code (I added static constexpr
, it was just an int
before):
static constexpr int ONE = 1;
setsockopt(socket_fd, IPPROTO_TCP, TCP_NODELAY, &ONE, sizeof(ONE));
Thanks!
Upvotes: 5
Views: 1165
Reputation: 180710
Every object is guaranteed to have an address per [intro.object]/8
An object has nonzero size if it
is not a potentially-overlapping subobject, or
is not of class type, or
is of a class type with virtual member functions or virtual base classes, or
has subobjects of nonzero size or bit-fields of nonzero length.
Otherwise, if the object is a base class subobject of a standard-layout class type with no non-static data members, it has zero size. Otherwise, the circumstances under which the object has zero size are implementation-defined. Unless it is a bit-field, an object with nonzero size shall occupy one or more bytes of storage, including every byte that is occupied in full or in part by any of its subobjects. An object of trivially copyable or standard-layout type ([basic.types]) shall occupy contiguous bytes of storage.
emphasis mine
Since ONE
is a non-class-non-bit-field type, it's in storage and you can take its address.
Upvotes: 4
Reputation: 72401
Yes, you can take the address of any object which is not a non-type non-reference template parameter or a bit-field. A variable declared constexpr
(or one which is implicitly a constant expression) can be used in more contexts, not fewer.
It's true that the compiler can often avoid using any memory storage for a constexpr
variable if it's not needed. But if the address is taken, that will probably require the memory storage, so the compiler will need to treat it more like an ordinary object in that case.
Upvotes: 6