Yeah, it's invalid, but not because you're converting a char*
to an A*
: it's because you are not obtaining a A*
that actually points to an A*
and, as you've identified, none of the type aliasing options fit.
You'd need something like this:
#include <new>
#include <iostream>
struct A
{
int t;
};
char *buf = new char[sizeof(A)];
A* ptr = new (buf) A;
ptr->t = 1;
// Also valid, because points to an actual constructed A!
A *ptr2 = reinterpret_cast<A*>(buf);
std::cout << ptr2->t;
Now type aliasing doesn't come into it at all (though keep reading because there's more to do!).
In reality, this is not enough. We must also consider alignment. Though the above code may appear to work, to be fully safe and whatnot you will need to placement-new
into a properly-aligned region of storage, rather than just a casual block of char
s.
The standard library (since C++11) gives us std::aligned_storage
to do this:
using Storage = std::aligned_storage<sizeof(A), alignof(A)>::type;
auto* buf = new Storage;
Or, if you don't need to dynamically allocate it, just:
Storage data;
Then, do your placement-new:
new (buf) A();
// or: new(&data) A();
And to use it:
auto ptr = reinterpret_cast<A*>(buf);
// or: auto ptr = reinterpret_cast<A*>(&data);
All in it looks like this:
#include <iostream>
#include <new>
#include <type_traits>
struct A
{
int t;
};
int main()
{
using Storage = std::aligned_storage<sizeof(A), alignof(A)>::type;
auto* buf = new Storage;
A* ptr = new(buf) A();
ptr->t = 1;
// Also valid, because points to an actual constructed A!
A* ptr2 = reinterpret_cast<A*>(buf);
std::cout << ptr2->t;
}
Even then, since C++17 this is somewhat more complicated; see the relevant cppreference pages for more information and pay attention to std::launder
.
Of course, this whole thing appears contrived because you only want one A
and therefore don't need array form; in fact, you'd just create a bog-standard A
in the first place. But, assuming buf
is actually larger in reality and you're creating an allocator or something similar, this makes some sense.