In the C++20 standard, it is said that array types are implicit lifetime type.
Does it mean that an array to a non implicit lifetime type can be implicitly created? The implicit creation of such an array would not cause creation of the array's elements?
Consider this case:
//implicit creation of an array of std::string
//but not the std::string elements:
void * ptr = operator new(sizeof (std::string) * 10);
//use launder to get a "pointer to object" (which object?)
std::string * sptr = std::launder(static_cast<std::string*>(ptr));
//pointer arithmetic on not created array elements well defined?
new (sptr+1) std::string("second element");
Is this code not UB any more since C++20?
Maybe this way is better?
//implicit creation of an array of std::string
//but not the std::string elements:
void * ptr = operator new(sizeof (std::string) * 10);
//use launder to get a "pointer to object" (actually not necessary)
std::string (* sptr)[10] = std::launder(static_cast<std::string(*)[10]>(ptr));
//pointer arithmetic on an array is well defined
new (*sptr+1) std::string("second element");
TC Answer + Comments conclusion:
- Array elements are not created but the array is created
- The use of
launder
in the first example cause UB, and is not necessary in the second example.
The right code is:
//implicit creation of an array of std::string
//but not the std::string elements:
void * ptr = operator new(sizeof (std::string) * 10);
//the pointer already points to the implicitly created object
//so casting is enough
std::string (* sptr)[10] = static_cast<std::string(*)[10]>(ptr);
//pointer arithmetic on an array is well defined
new (*sptr+1) std::string("second element");
std::string
is created, the language allows to deduce thatstatic_cast<std::string*>
points to the first element of the array and not just random string? Or only the second variant is valid? – Yinglingstd::launder
. Withoutstd::launder
it would be correct. – Hildegardhildegardestd::string (* sptr)[10] = static_cast<std::string(*)[10]>(ptr);
is that it doesn't scale if you want to replace 10 with n - in order to dynamically allocate memory. – Yinglingstd::string * sptr = static_cast<std::string *>(ptr)
– Hildegardhildegardelaunder(reinterpret_cast<T*>(new (p) byte[n * sizeof(T)]))
is not a legal use of launder according to the comments to the answer (no T is created...). On the other hand, you run into problems withoutlaunder
either, as far as I know. Standard is not clear whetherlaunder
can be used tolegalize
pointer arithmetic - as far as I am aware it doesn't state that. – Yinglingallocate(n)
would not produce a a pointer to a suitable created object. butmalloc
would do? – Hildegardhildegardestd::allocator<T>
- they are allowed to be "magic" and "implementation defined". – Yingling