Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Type Traits of trivially serializable C++ classes

I have a C++ class defined as A a; which I would like to serialize. The simplest way to do this (when it works) is

write(fd, reinterpret_cast<uint8_t*>(&a), sizeof(a));

and to read it back using:

read(fd, reinterpret_cast<uint8_t*>(&a), sizeof(a));

I know that this will work if std::is_pod<A>::value is true types but what is the most relaxed set of type traits A must exibit for this to to work?

Just for completeness, this is for persistence between running instances of the application, there is no need for the file to be readable by another program or on another platform.

like image 260
doron Avatar asked Aug 15 '16 10:08

doron


People also ask

What is serialize C++?

Serialization is the process of writing or reading an object to or from a persistent storage medium such as a disk file. Serialization is ideal for situations where it is desired to maintain the state of structured data (such as C++ classes or structures) during or after execution of a program.

How do you serialize a structure in C++?

use std::string or std::vector<byte> to hold the serialized data (and dispose of that #define PACKETSIZE altogether) and use it as a return value of the serialize function instead of the output parameter (or if you insist change the parameter to char(&data)[PACKETSIZE] ). This is a good simple implementation, true.

How do you serialize an object in C++?

Serializing whole objects To unserialize an object, it should have a constructor that takes byte stream. It can be an istream but in the simplest case it can be just a reference uint8_t pointer. The constructor reads the bytes it wants from the stream and sets up the fields in the object.

How do you serialize a class in CPP?

Object Serialization with the Boost C++ Library Note that, for each class to be serialized, there is a template function that saves the whole class definition. The classes should be restored in the same sequence they were stored. This is particularly important if different objects are stored in the same file.


2 Answers

Writing the bitwise image of an object into a stream and restoring it correctly by reading from that stream is exactly the same as the object behaving correctly under memcpy. And for that, there's the specific property of begin trivially copyable. So the trait you want to use is std::is_trivially_copyable<A>.


Unrelated side note: Your code could theoretically have Undefined Behaviour. That is because C++ only allows aliasing through types char and unsigned char, and there's no guarantee that std::uint8_t is an alias for one of those. You'd better off using unsigned char explicitly:

write(fd, reinterpret_cast<unsigned char*>(&a), sizeof(a));
like image 89
Angew is no longer proud of SO Avatar answered Nov 03 '22 01:11

Angew is no longer proud of SO


What you are looking for is is_trivially_copyable, as per agnew's answer. However, this does not mean trivially serializable because of

  • different data type sizes on different compilers / compile options
  • different alignment on different compilers / platforls / compile options
  • byte order on different platforms

Furthermore, you will run into problems with versioning, and the meaning of data may be different on different execution machines.

That's why I would recommend to introduce a custom trait,is_doron_serializabe, and have it default to false for types not explicitely marked as compatible.

(What you are planning may be OK in some circumstances.)

like image 44
peterchen Avatar answered Nov 02 '22 23:11

peterchen