I'm trying to define a Data
object that contains its size, followed by size
bytes of data.
Something like:
struct Data {
size_t size;
char data[1];
static void* operator new( std::size_t size, size_t dataSize ) {
return ::operator new( size+dataSize-1 );
}
static void operator delete( void* data ){
::operator delete( data );
}
Data( size_t size ) : size(size) {
std::memset( data, 0, size );
}
};
This works, and I can allocate it with placement new:
Data* data = new (3) Data( 3 );
I'd like to create a std::unique_ptr<Data>
and, as good practice, I'd prefer to use std::make_uinque
, over a raw new
.
Is it possible to call std::make_unique<Data>
passing it the data for placement-new?
Any version of the C++ standard is fine.
There is no standard way to do this, because standard C++ doesn't provide any real support for VLAs/flexible array members. make_unique
was written solely for either:
new
, which assumes sizeof T
is correct and complete)I suppose in theory you could make your own version that supported quasi-flexible array members, but there is zero support for this in the C++ standard library. std::make_unique
doesn't even have an allocator-aware variant; it's not going out of its way to support unusual use cases. std::allocate_shared
(the allocator aware version of std::make_shared
) might be forced to support this in ridiculous ways (you'd essentially need to write custom allocators that also knew how much extra memory an allocation request should provide), and there's a proposal for an allocator-aware version of std::make_unique
, but again, making this work would be an exercise in insanity.
You say "as good practice, I'd prefer to use std::make_unique
, over a raw new
", but flexible array members in C++ are already bad practice; there is essentially zero support for them because they break all sorts of assumptions that much of the C++ language and library rely on. If you must do it, write your own factory methods to perform the work; sure, using raw new
is frowned on, but confining it to a single API in your code that guarantees the result is a managed pointer before passing it outside that API limits the "damage".