No no.
If we had a full reflection (approaching the C ++ standard next to you 2014 2017 2020!), You could write your own character to some extent.
But even there you ran into a problem.
A std::size_t
may be a value or an index in some const char*
hash table, sown at their memory location. It is unsafe to write out such a value, and then read further at the next program execution.
Also, the reading code may not agree with how large a int
. So now you have to distinguish between int32_t
and int
, both of which are allowed for the same type in compiler 1, but different types in compiler 2 (or even in compiler settings!).
It is best to use your own trait like the Koenig flag function, which claims that something is safe for binary serialization, with some excessive security checks (generate errors if the type no longer matches, standard layout, trivially copied, etc.).
In addition, you must use the archive system. Add a reflection that allows you to read / write the state of the object. Make aggregation objects easy recursively.
template<class Stream> void Archive( Stream& s ) { s.start(*this)->*[&]{ s & field1; s & field2; s & field3; }; }
where this code breaks down into a reading or writing mechanism depending on the type of Stream
, encodes a header and (optionally) a type flag for *this
and length. Then it transfers the contents to / from. Additional materials at the end are automatically discarded.
For binary types:
template<class Stream> void Archive( Stream& s ) { FlatBinary( *this, s ); }
does everything for you, but still guarantees alignment of sizes, etc. (letting the structure grow in future versions without any errors!) We can even detect flat binary types and not use Archive
through the flag.
Placed:
friend std::true_type is_flat_binary_test( BobType ) { return {}; }
in these types. Then do
namespace flat_binary_details { template<class T> inline std::false_type is_flat_binary_test( T ) { return {}; } template<class T> inline auto flat_binary_f() -> decltype( is_flat_binary_test( std::declval<T>() ) ) { return {}; } } template<class T> using is_flat_binary = decltype( details::flag_binary_f<T>() );
Now is_flat_binary< std::vector<int> >
is false_type
, and
namespace X { struct Bob { friend std::true_type is_flat_binary_test( Bob );
just works.
Your archive system can test all objects marked as flat binary files and implement an efficient archiving system for them. Without it, he can detect a member of the Archive( Stream& )
and call it. Without it, it can detect Read
and Write
. Custom design types can be extended. You can write a non-member Achive
for std
types.
But it is too far. In short, archiving material is difficult; find the structure.