Why doesn't [[no_unique_address]] work on objects of the same type? [duplicate]

1 day ago 4
ARTICLE AD BOX

The C++ standard prevents two objects of the same type existing at the same address in [intro.object] p10:

Unless an object is a bit-field or a subobject of zero size, the address of that object is the address of the first byte it occupies. Two objects with overlapping lifetimes that are not bit-fields may have the same address if

one is nested within the other, at least one is a subobject of zero size and they are not of similar types ([conv.qual]), or they are both potentially non-unique objects;

otherwise, they have distinct addresses and occupy disjoint bytes of storage.

All subobjects of type E could be zero-size because [[no_unique_address]] marks them as potentially-overlapping subobjects. However, the three E subobjects in S3 are all of similar type, so they may not have the same address regardless.

If the standard permitted them to exist at the same address, it would become ambiguous which E subobject you obtain a pointer to via std::launder(reinterpret_cast<E*>(...)).

Jan Schultke's user avatar

2 Comments

That last sentence was the insight I needed, thanks! Though it does make me wonder: how does the distinction matter? They're all overlapping and zero-sized, so... what even distinguishes them? What is the actual problem?

2026-01-26T05:15:08.703Z+00:00

Maybe from a hardware perspective, it wouldn't be a problem, but the wording mechanics are unclear. Standard-layout types are pointer-interconvertible with their first member. If you obtained an E*, would it be valid to reinterpret_cast<S1*> because that E* could be the first member of an S1 object? If so, doesn't that imply you have a pointer to an object that's simultaneously the first member of three different subobjects? It's all very strange; the standard doesn't have a notion of these "superposition pointers" to multiple objects; a pointer points to one object.

2026-01-26T05:29:19.29Z+00:00

Read Entire Article