Wouldn't a bunch of function overloads for the different primitive types be nicer here? I.e. you'd then just write packer.Write(...) each time, and if you change the data type of a field, it's dealt with by the compiler in the serialization code.
I've thought of that, but that may cause unexpected errors with implicit type conversion. Which overload is chosen for a time_t? A uint32_t or a sint32_t? Oh, sorry, implementation defined! It might even be a 64 bits on a 64 bit computer.
Plus, just because I have something as a 'unsigned int' in my structure or class, doesn't mean I always want it to take 32 bits in a network packet or a data file. Being explicit of the storage in this situation I think is actually a plus, though I should comment that a 'bool' I store in a single byte instead of a one bit.
I'd like to add overloads for vectors of common types also, in the same way I handle std::string. (Write the size, then read the number of elements).
I *would* like to make reading and writing functions identical. Something like this:
BytePacker bytePacker(Mode::Read or Mode::Write);
//All of myStruct's members are passed in by reference, so if Mode is Read, the data is read and the struct is written to,
//and if the Mode is Write, then the data is written to and the struct's members and read from.
But that's not implemented yet.