Charlie Charlie - 25 days ago 6
C++ Question

Is an object valid in serialized form? c++/inheritance/serialization

I'm asking this because even tho it seems to work, I feel like it shouldn't. The goal is to have a collection of objects kept alive, and general access to them. This is what I have at the moment:

Take a base pointer access:

struct base {virtual void tick() = 0; }//ptr access


With different types that inherit from it:

struct :public base
{
int x,y; //2 ints
void tick() { cout << "im type 1" << endl; }
}type1;

struct :public base
{
int x,y,z; //3 ints to make it different
void tick() { cout << "im type 2" << endl; }
}type2;


Then a container class that should be able to store any amount of these serialized:

class xtype
{
vector<char>charcast;

public:

template<typename T> base* serial_acc(T &input) //take object, return (base*)
{
charcast.resize(sizeof(input)); //size for serialize
memcpy(charcast.data(), (char*)&input, sizeof(input)); //copy into vector

return (base*)charcast.data(); //return base ptr to serialized object
}
}xcontainer;


Then call:

base* base_ptr; //the access pointer
base_ptr = xpointer.serial_acc(type1); //type that inherits from base


And you can access a serialized version of the object by doing:

base_ptr->tick(); //which will output "im type 1" to console


But is this legal? Does this serialized version have a proper type? Is accessing a serialized object directly with a base pointer illegal or wrong?




Answer: the types return false on is_trivially_copyable meaning its not safe.

Answer

What you are doing is illegal. You can only memcpy an object as an array of chars when the object is TriviallyCopyable. And your object is not, since it has virtual functions.

Instead of doing this, you should simply store a (unique) pointer to newly allocated object, and avoid any casts to enforce hierarchy. Like this:

class xtype
{
    std::unique_ptr<base> ptr;

public:

    template<typename T> base* serial_acc(T &input) //take object, return (base*)
    { 
        static_assert(std::is_base_of<base, T>::value, "Please use proper type");
        ptr = std::make_unique<base>(input);
        return ptr;
    }  
} xcontainer;
Comments