serialization: pointer reconstruction

A while back I asked about saving a pointer to an item in another class that is stored as a direct instance variable (no pointer). Here's a brief illustration: struct A { }; struct B { A a; }; struct C { A * a; // points to a B::a. }; I have an idea how to store and restore these relationships but I'd like to see if there are any improvement ideas and/or direction to existing behavior I'm not seeing in the documentation. My idea is to first store B::a (which simply makes sense in my problem anyway) and when I do this to call some custom support functions to generate a unique ID for the object at that address and store it first, then the rest of the data in A. This would appear in A::serialize and the unique ID would be stored in the Archive (added behavior) as a map from address to uid. Then when storing C I would request the unique ID for the address the pointer stores and store it. On reading I read B::a first and it sort of reverses the process. The uid is read and then A::serialize stores the uid and 'this' in the archive map in a uid->address format. I then read the uid on reading C::a and request the address from the archive using that value. I've already subclassed the Archive in order to pass around other load information needed by classes that didn't have local copies, so that's the easy part (though it wasn't a straight forward operation). The question I have though is that since the pointer archiving already must use some similar type of API, can I use it instead of rolling my own and how would I do that?

I believe that what you want to do is already handled automatically by the serialization library. The only requirement is that struct B be serialized before struct C. The serialization library handles all the id management internally. Robert Ramey Noah Roberts wrote:
A while back I asked about saving a pointer to an item in another class that is stored as a direct instance variable (no pointer). Here's a brief illustration:
struct A { };
struct B { A a; };
struct C { A * a; // points to a B::a. };
I have an idea how to store and restore these relationships but I'd like to see if there are any improvement ideas and/or direction to existing behavior I'm not seeing in the documentation.
My idea is to first store B::a (which simply makes sense in my problem anyway) and when I do this to call some custom support functions to generate a unique ID for the object at that address and store it first, then the rest of the data in A. This would appear in A::serialize and the unique ID would be stored in the Archive (added behavior) as a map from address to uid.
Then when storing C I would request the unique ID for the address the pointer stores and store it.
On reading I read B::a first and it sort of reverses the process. The uid is read and then A::serialize stores the uid and 'this' in the archive map in a uid->address format. I then read the uid on reading C::a and request the address from the archive using that value.
I've already subclassed the Archive in order to pass around other load information needed by classes that didn't have local copies, so that's the easy part (though it wasn't a straight forward operation). The question I have though is that since the pointer archiving already must use some similar type of API, can I use it instead of rolling my own and how would I do that?

In article
I believe that what you want to do is already handled automatically by the serialization library. The only requirement is that struct B be serialized before struct C. The serialization library handles all the id management internally.
You're right, I don't know why I thought it necessary. However, in bringing this into production code I realized that my example wasn't completely similar. There's an important difference that I don't understand why it's important. Struct C actually looks like so: struct C { A const* a; }; In order to serialize C I needed to make the serialize member function look like so: template < typename Archive > void serialize(Archive & ar, unsigned int const) { A *& ptr = const_cast(a); ar & a; } Simply attempting to archive the pointer to constant directly resulted in bad things. Namely a compiler vomit about inability to reinterpret_cast to a non-const **. Is there a safer workaround?
Robert Ramey
Noah Roberts wrote:
A while back I asked about saving a pointer to an item in another class that is stored as a direct instance variable (no pointer). Here's a brief illustration:
struct A { };
struct B { A a; };
struct C { A * a; // points to a B::a. };
I have an idea how to store and restore these relationships but I'd like to see if there are any improvement ideas and/or direction to existing behavior I'm not seeing in the documentation.
My idea is to first store B::a (which simply makes sense in my problem anyway) and when I do this to call some custom support functions to generate a unique ID for the object at that address and store it first, then the rest of the data in A. This would appear in A::serialize and the unique ID would be stored in the Archive (added behavior) as a map from address to uid.
Then when storing C I would request the unique ID for the address the pointer stores and store it.
On reading I read B::a first and it sort of reverses the process. The uid is read and then A::serialize stores the uid and 'this' in the archive map in a uid->address format. I then read the uid on reading C::a and request the address from the archive using that value.
I've already subclassed the Archive in order to pass around other load information needed by classes that didn't have local copies, so that's the easy part (though it wasn't a straight forward operation). The question I have though is that since the pointer archiving already must use some similar type of API, can I use it instead of rolling my own and how would I do that?

Noah Roberts wrote:
In article
, ramey@rrsd.com says... I believe that what you want to do is already handled automatically by the serialization library. The only requirement is that struct B be serialized before struct C. The serialization library handles all the id management internally.
You're right, I don't know why I thought it necessary. However, in bringing this into production code I realized that my example wasn't completely similar. There's an important difference that I don't understand why it's important. Struct C actually looks like so:
struct C { A const* a; };
In order to serialize C I needed to make the serialize member function look like so:
template < typename Archive > void serialize(Archive & ar, unsigned int const) { A *& ptr = const_cast(a); ar & a; }
Simply attempting to archive the pointer to constant directly resulted in bad things. Namely a compiler vomit about inability to reinterpret_cast to a non-const **.
Is there a safer workaround?
Currently in the TRAC database is an item which points out this problem. Also someone else recently had a similar situation. I haven't had time to give the scrutiny it deserves. A simple workaround would be to just relace A const * with A *.
Robert Ramey
Noah Roberts wrote:
A while back I asked about saving a pointer to an item in another class that is stored as a direct instance variable (no pointer). Here's a brief illustration:
struct A { };
struct B { A a; };
struct C { A * a; // points to a B::a. };
I have an idea how to store and restore these relationships but I'd like to see if there are any improvement ideas and/or direction to existing behavior I'm not seeing in the documentation.
My idea is to first store B::a (which simply makes sense in my problem anyway) and when I do this to call some custom support functions to generate a unique ID for the object at that address and store it first, then the rest of the data in A. This would appear in A::serialize and the unique ID would be stored in the Archive (added behavior) as a map from address to uid.
Then when storing C I would request the unique ID for the address the pointer stores and store it.
On reading I read B::a first and it sort of reverses the process. The uid is read and then A::serialize stores the uid and 'this' in the archive map in a uid->address format. I then read the uid on reading C::a and request the address from the archive using that value.
I've already subclassed the Archive in order to pass around other load information needed by classes that didn't have local copies, so that's the easy part (though it wasn't a straight forward operation). The question I have though is that since the pointer archiving already must use some similar type of API, can I use it instead of rolling my own and how would I do that?
participants (2)
-
Noah Roberts
-
Robert Ramey