1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
|
#include <iostream>
#include <type_traits>
#include <memory>
template < typename T > std::ostream& write_bytes( std::ostream& stm, const T& object )
{
return stm.write( reinterpret_cast< const char* >( std::addressof(object) ), sizeof(object) ) ;
}
// invariant: object is not the base class sub-object of an object of a more derived type
// *** alert: if it is a base class sub-object, this will engender undefined behaviour ****
// invariant: T is TriviallyCopyable
// *** alert: if it not TriviallyCopyable, the static assertion will fail ****
template < typename T > std::istream& read_as_bytes( std::istream& stm, T& object )
{
static_assert( std::is_trivially_copyable<T>::value, "error: object is not of a TriviallyCopyable type" ) ;
return stm.read( reinterpret_cast<char*>( std::addressof(object) ), sizeof(object) ) ;
}
#include <sstream>
int main()
{
std::stringstream stm ;
struct A { int i ; double d ; };
A a { 1, 2.3 };
write_bytes( stm, a ) ;
a = {} ;
std::cout << a.i << ' ' << a.d << '\n' ; // 0 0
read_as_bytes( stm, a ) ; // fine
std::cout << a.i << ' ' << a.d << '\n' ; // 1 2.3
struct B final { int i ; std::string s; };
B b { 1, "2.3" };
write_bytes( stm, b ) ;
read_as_bytes( stm, b ) ; // *** error: object is not of a TriviallyCopyable type
struct C : virtual A {};
C c ;
c.i = c.d = 0 ;
A& sub_object = c ;
write_bytes( stm, sub_object ) ;
read_as_bytes( stm, sub_object ) ; // **** undefined behaviour **** (base-class sub-object)
}
|