I have a struct representing a binary message. I want to write a function to get the next such record from a buffer (whether a file or a socket, doesn't matter):
template <typename Record>
Record getNext();
Now, I could write this like:
template <typename Record>
Record getNext() {
Record r;
populateNext(reinterpret_cast<char*>(&r), // maybe ::read()
sizeof(r)); // or equivalent
return r;
}
which is nice and gives me the benefits of RVO. However, it will invoke the default constructor of Record
, which may be composed of types with non-trival default constructors which do work that I would like to avoid - these are not necessarily POD types, but they are standard layout.
Is there a way to write getNext()
such that we avoid any constructors (default or copy/move) on Record
? Ideally, when the user calls:
auto record = getNext<Record>();
The buffer is read directly into the memory of record
. Is this possible?
no_init
is a constant of typeno_init_t
.If you construct a pod from a
no_init_t
, you get an uninitialized pod, and (assuming elision) there is nothing to be done.If you construct a non-pod from a
no_init_t
, you have to override a constructor, and make it not initialize the data. Usuallyclass_name(no_init_t):field1(no_init), field2(no_init){}
will do it, and sometimesclass_name(no_init_t){}
will do it (assuming all contents are pod).Constructing from
no_init
on each member can act as a sanity check that the members are indeed pod, however. A non-pod class constructed fromno_init
will fail to compile until you write theno_init_t
constructor.This (having to
no_init
each member constructor) does generate some annoying DRY failure, but we don't got reflection, so you are gonna repeat yourself and like it.Now we can construct
Record
withno_init
and it won't be initialized.Every POD class is not initialized. Every non-POD class must provide a
no_init_t
constructor (and presumably implement non-initialization, as best it can).You then
memcpy
right over it.This requires modifying your type, and the types it contains, to support non-initialization.