Consider the following sample code:
struct X { const int n; };
union U { X x; float f; };
void fun() {
U u = {{ 1 }};
u.f = 5.f; // OK, creates new subobject of 'u'
X *p = new (&u.x) X {2}; // OK, creates new subobject of 'u'
if(*std::launder(&u.x.n) == 2){// condition is true because of std::launder
std::cout << u.x.n << std::endl; //UB here?
}
}
What will function fun
prints according to the language standard? In other words, does the effect of std::launder
last beyond the expression in which it is called? Or, we have to use std::launder
each time we need to access the updated value of u.x.n
?
cppereference is quite explicit about it:
std::launder has no effect on its argument. Its return value must be used to access the object. Thus, it's always an error to discard the return value.
As for the standard itself, nowhere does it state that its argument is also laundered (or not), but the signature of the function indicates that in my opinion: the pointer is taken by value, not by reference, thus it cannot be altered in any way visible to the caller.