Consider the following three programs:
// program 1
#include<new>
struct A {
const int a = 0;
int b = 0;
};
int main() {
auto a = new A[2];
new(a+1) A;
a[1].b = 1;
}
// program 2
#include<new>
struct A {
const int a = 0;
int b = 0;
};
int main() {
auto a = new A[2];
new(a) A;
a[0].b = 1;
}
// program 3
#include<new>
struct A {
const int a = 0;
int b = 0;
};
int main() {
auto a = new A[2];
new(a) A;
a->b = 1;
}
Do these programs have undefined behavior in C++17?
The problem I see is that according to [basic.life]/8 pointers will not automatically refer to the new A objects that I am creating via placement-new. std::launder is required explicitly to achieve that. Thus the member access will have undefined behavior as it is done on an object outside its lifetime.
At least for program 3 this seems clear to me, but for program 1, according to [intro.object]/2 the newly created object becomes a subobject of the array and so it should be reached via pointer arithmetic, shouldn't it?
And program 2 would then also not have undefined behavior, because the pointer arithmetic only requires a to point to an element of the array, not necessarily in its lifetime.