[serialization] Inherited objects

I've gone through the documentation, and I'm still unable to get this particular aspect of serialization working. I have two objects 'a' and 'b', and 'b' inherits from 'a'. I have a vector of 'a' pointers that may just be 'a' or may be 'b'. I've preregistered 'b', right before the vector serialization occurs, so that the serialization system should properly recognize that 'b' inherits from 'a'. However, only the 'a' pieces of each 'b' in the vector serializes. If I place all the 'b' items in a second 'b' containing vector, and serialize that afterwards, it properly discovers that the 'a' part has been serialized already and simply points to that reference. I don't really want to store this second 'b' vector. Is there a way to get a vector of a items to also serialize the 'b' part of the element if the item is a 'b'? I apologize if this is already in the documentation, but if it is, I missed it. Also, there is an issue in the documentation. In the "Pointers to Objects of Derived Classes" section, it has example registration code: main(){ ... ar.template register_type<derived_one>(); ar.template register_type<derived_two>(); base *b; ar & b; } I'm guessing that is supposed to be: main(){ ... ar.register_type<derived_one>(); ar.register_type<derived_two>(); base *b; ar & b; } Thanks, Jared

On Mon, Oct 10, 2005 at 11:42:36AM -0600, Jared McIntyre wrote:
I've gone through the documentation, and I'm still unable to get this particular aspect of serialization working. I have two objects 'a' and 'b', and 'b' inherits from 'a'. I have a vector of 'a' pointers that may just be 'a' or may be 'b'. I've preregistered 'b', right before the vector serialization occurs, so that the serialization system should properly recognize that 'b' inherits from 'a'. However, only the 'a' pieces of each 'b' in the vector serializes. If I place all the 'b' items in a second 'b' containing vector, and serialize that afterwards, it properly discovers that the 'a' part has been serialized already and simply points to that reference. I don't really want to store this second 'b' vector. Is there a way to get a vector of a items to also serialize the 'b' part of the element if the item is a 'b'?
You might want to post some code that shows what's wrong. Have you tried informing the archives of the existence of derived 'b' via BOOST_CLASS_EXPORT(b)? And does your 'b' correctly serialize it's base class 'a' via base_object<> ?
Also, there is an issue in the documentation. In the "Pointers to Objects of Derived Classes" section, it has example registration code:
main(){ ... ar.template register_type<derived_one>(); ar.template register_type<derived_two>(); base *b; ar & b; }
I'm guessing that is supposed to be:
main(){ ... ar.register_type<derived_one>(); ar.register_type<derived_two>(); base *b; ar & b; }
Doesn't matter what order they're registered in. Just that they're registered. HTH, -t

Double check that a is polymorphic - that is, that it has at least one virtual function. Then get back to us. Robert Ramey Jared McIntyre wrote:
I've gone through the documentation, and I'm still unable to get this particular aspect of serialization working. I have two objects 'a' and 'b', and 'b' inherits from 'a'. I have a vector of 'a' pointers that may just be 'a' or may be 'b'. I've preregistered 'b', right before the vector serialization occurs, so that the serialization system should properly recognize that 'b' inherits from 'a'. However, only the 'a' pieces of each 'b' in the vector serializes. If I place all the 'b' items in a second 'b' containing vector, and serialize that afterwards, it properly discovers that the 'a' part has been serialized already and simply points to that reference. I don't really want to store this second 'b' vector. Is there a way to get a vector of a items to also serialize the 'b' part of the element if the item is a 'b'?
I apologize if this is already in the documentation, but if it is, I missed it.
Also, there is an issue in the documentation. In the "Pointers to Objects of Derived Classes" section, it has example registration code:
main(){ ... ar.template register_type<derived_one>(); ar.template register_type<derived_two>(); base *b; ar & b; }
I'm guessing that is supposed to be:
main(){ ... ar.register_type<derived_one>(); ar.register_type<derived_two>(); base *b; ar & b; }
nope, its correct. This is a little known quirk of C++ syntax. Your second version won't compile on the most conforming compilers. Robert Ramey
Thanks,
Jared _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Robert Ramey wrote:
Double check that a is polymorphic - that is, that it has at least one virtual function. Then get back to us.
Robert Ramey Jared McIntyre wrote: <snip>
Also, there is an issue in the documentation. In the "Pointers to Objects of Derived Classes" section, it has example registration code:
main(){ ... ar.template register_type<derived_one>(); ar.template register_type<derived_two>(); base *b; ar & b; }
I'm guessing that is supposed to be:
main(){ ... ar.register_type<derived_one>(); ar.register_type<derived_two>(); base *b; ar & b; }
nope, its correct. This is a little known quirk of C++ syntax. Your second version won't compile on the most conforming compilers.
Not according to Comeau: "ComeauTest.c", line 16: error: the "template" keyword used for syntactic disambiguation may only be used within a template

Simon Buchan wrote:
Robert Ramey wrote:
Double check that a is polymorphic - that is, that it has at least one virtual function. Then get back to us.
Robert Ramey Jared McIntyre wrote: <snip>
Also, there is an issue in the documentation. In the "Pointers to Objects of Derived Classes" section, it has example registration code:
main(){ ... ar.template register_type<derived_one>(); ar.template register_type<derived_two>(); base *b; ar & b; }
I'm guessing that is supposed to be:
main(){ ... ar.register_type<derived_one>(); ar.register_type<derived_two>(); base *b; ar & b; }
nope, its correct. This is a little known quirk of C++ syntax. Your second version won't compile on the most conforming compilers.
Not according to Comeau: "ComeauTest.c", line 16: error: the "template" keyword used for syntactic disambiguation may only be used within a template
whoops - wrong again. If ar is a template you need "ar.template" other wise you shouldn't have it. From the above code it could be either. Its really annoying to me to have to keep the context and provinence of a variable like "ar" in my head while I'm writting. So I actually prefer the universal, idiot proof workaround: ar.register_type(static_cast<derived_one *>(NULL)) which works on all compilers conforming or not regardless of whether ar is a template or not. Robert Ramey
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

"Robert Ramey" <ramey@rrsd.com> writes:
Simon Buchan wrote:
Robert Ramey wrote:
Double check that a is polymorphic - that is, that it has at least one virtual function. Then get back to us.
Robert Ramey
I'm guessing that is supposed to be:
main(){ ... ar.register_type<derived_one>(); ar.register_type<derived_two>(); base *b; ar & b; }
nope, its correct. This is a little known quirk of C++ syntax. Your second version won't compile on the most conforming compilers.
Not according to Comeau: "ComeauTest.c", line 16: error: the "template" keyword used for syntactic disambiguation may only be used within a template
whoops - wrong again. If ar is a template you need "ar.template" other wise you shouldn't have it.
Nope, wrong again. If ar's type X is dependent and "register_type" is a nested template in X, then you need "ar.template register_type<...>". Otherwise, you need "ar.register_type<...>"
From the above code it could be either. Its really annoying to me to have to keep the context and provinence of a variable like "ar" in my head while I'm writting.
Guess what; you don't. If you had to know whether ar was a template or not, just think how impossible it would be to write generic code? -- Dave Abrahams Boost Consulting www.boost-consulting.com

David Abrahams wrote:
"Robert Ramey" <ramey@rrsd.com> writes:
Simon Buchan wrote:
Robert Ramey wrote:
Double check that a is polymorphic - that is, that it has at least one virtual function. Then get back to us.
Robert Ramey
I'm guessing that is supposed to be:
main(){ ... ar.register_type<derived_one>(); ar.register_type<derived_two>(); base *b; ar & b; }
nope, its correct. This is a little known quirk of C++ syntax. Your second version won't compile on the most conforming compilers.
Not according to Comeau: "ComeauTest.c", line 16: error: the "template" keyword used for syntactic disambiguation may only be used within a template
Quick note: Comeau (possibly the worlds most conforming compiler) doesn't actually require the template disambiguator (despite allowing it in the correct case), when I asked them why (support@comeaucomputing.com), they replied with:
" We believe there is enough wiggle room and amibiguity in the standard " about that requirement, and also, some direction that if the rule does " exist, that it might be relaxed. So basically, they don't think it's _really_ that required by the standard. (Personally, I believe at least a warning in strict mode would be nice)
whoops - wrong again. If ar is a template you need "ar.template" other wise you shouldn't have it.
Nope, wrong again. If ar's type X is dependent and "register_type" is a nested template in X, then you need "ar.template register_type<...>". Otherwise, you need "ar.register_type<...>"
A-la typename usage: typename dependant_name::nested_type dependant_name.template nested_template
From the above code it could be either. Its really annoying to me to have to keep the context and provinence of a variable like "ar" in my head while I'm writting.
Guess what; you don't. If you had to know whether ar was a template or not, just think how impossible it would be to write generic code?
Well, you *do* have to know if ar is a class template, but not if it's a template class, which is what I think you were trying to say.

Simon Buchan <simon@hand-multimedia.co.nz> writes:
Nope, wrong again. If ar's type X is dependent and "register_type" is a nested template in X, then you need "ar.template register_type<...>". Otherwise, you need "ar.register_type<...>"
A-la typename usage:
typename dependant_name::nested_type
dependant_name.template nested_template
Exactemundo.
From the above code it could be either. Its really annoying to me to have to keep the context and provinence of a variable like "ar" in my head while I'm writting.
Guess what; you don't. If you had to know whether ar was a template or not, just think how impossible it would be to write generic code?
Well, you *do* have to know if ar is a class template, but not if it's a template class, which is what I think you were trying to say.
No, I was using colloquialism. After all, "ar" is a variable, not a type or a template. The only interpretation that could possibly make sense is that I meant "ar's type is a class template specialization." -- Dave Abrahams Boost Consulting www.boost-consulting.com

David Abrahams wrote:
"Robert Ramey" <ramey@rrsd.com> writes:
Simon Buchan wrote:
Robert Ramey wrote:
Double check that a is polymorphic - that is, that it has at least one virtual function. Then get back to us.
Robert Ramey
I'm guessing that is supposed to be:
main(){ ... ar.register_type<derived_one>(); ar.register_type<derived_two>(); base *b; ar & b; }
nope, its correct. This is a little known quirk of C++ syntax. Your second version won't compile on the most conforming compilers.
Not according to Comeau: "ComeauTest.c", line 16: error: the "template" keyword used for syntactic disambiguation may only be used within a template
whoops - wrong again. If ar is a template you need "ar.template" other wise you shouldn't have it.
Nope, wrong again. If ar's type X is dependent and "register_type" is a nested template in X, then you need "ar.template register_type<...>". Otherwise, you need "ar.register_type<...>"
From the above code it could be either. Its really annoying to me to have to keep the context and provinence of a variable like "ar" in my head while I'm writting.
Guess what; you don't. If you had to know whether ar was a template or not, just think how impossible it would be to write generic code?
Hmmm - here is a situation that I come across: class my_archive { .... }; template<class Arg> class my_templated_archive{ }; template<class Archive, T> void serialize(Archive & ar, T &t, const unsigned int version){ ... ar.template register_type<T>(); // ok - I think ... } void serialize(my_archive & ar, T &t, const unsigned int version){ ... ar.template register_type<T>(); // syntax error? or not? ... } Truth is I can't never keep these kinds of rules straight. Robert Ramey

Robert Ramey wrote:
void serialize(my_archive & ar, T &t, const unsigned int version){ ... ar.template register_type<T>(); // syntax error? or not?
Syntax error, if 'my_archive' is a real (as opposed to 'dependent') type.
... }
Truth is I can't never keep these kinds of rules straight.
If the type 'ar' is dependent on template parameters, the compiler can't look up symbols inside it, as these symbols may have different bindings for different template specializations of 'ar'. Thus, to make further parsing possible you have to tell the compiler to treat the following token as a template-name, or else 'register_type<T' will be parsed as a relational expression involving operands register_type and T. HTH, Stefan

"Robert Ramey" <ramey@rrsd.com> writes:
Hmmm - here is a situation that I come across:
class my_archive { .... };
template<class Arg> class my_templated_archive{ };
template<class Archive, T> void serialize(Archive & ar, T &t, const unsigned int version){ ... ar.template register_type<T>(); // ok - I think ... }
Correct.
void serialize(my_archive & ar, T &t, const unsigned int version){ ... ar.template register_type<T>(); // syntax error? or not? ... }
Syntax error, at least unless and until the committee relaxes the rules. my_archive is not a dependent type.
Truth is I can't never keep these kinds of rules straight.
It's pretty simple: does the type of ar depend on a template parameter? If so, we don't know whether ar.register_type is a value or a class template and template is required. If not, we can simply look at the type of ar and determine whether register_type is a template or not, and the template keyword is forbidden. -- Dave Abrahams Boost Consulting www.boost-consulting.com

Robert Ramey wrote: <snip>
Hmmm - here is a situation that I come across:
class my_archive { .... };
template<class Arg> class my_templated_archive{ };
template<class Archive, T> ^ you forgot 'class' here :-) void serialize(Archive & ar, T &t, const unsigned int version){ ... ar.template register_type<T>(); // ok - I think ... }
void serialize(my_archive & ar, T &t, const unsigned int version){ ... ar.template register_type<T>(); // syntax error? or not? ... }
Truth is I can't never keep these kinds of rules straight.
Robert Ramey
In the first: ar is dependant, so the lookup of register_type cannot happen until serialize is instatiated: but the syntax must be checked due to two-stage lookup. (which, believe it or not, actually helps more than it hinders, as long as you arn't a compiler vendor) Since it has no idea what register_type is (it could be an int, for all it knows) it simply assumes it isn't a template and treats it as a couple of comparisons. (Which gives an error when it finds out later that register_type is a template) Which is why you need the template keyword there. In the second, it can look up all the types right there and then, so there is no need for (and is illegal to add) the disambiguation. BTW: it doesn't matter whether *ar* comes from a template or not, they're all classes at that point. What matters is that it's being *used* in a template and is dependant on a parameter, and thus can't be looked up right there and then, meaning the compiler doesn't know what register_type is. Nifty huh? </sarcasm> The good news is that most of the time, none of this matters much to you. If it complains, add the keyword and be thankful your compiler is conformant.

Simon Buchan <simon@hand-multimedia.co.nz> writes:
The good news is that most of the time, none of this matters much to you. If it complains, add the keyword and be thankful your compiler is conformant.
That policy might work okay for the average user, but it's not really appropriate for a library developer trying to write portable code. -- Dave Abrahams Boost Consulting www.boost-consulting.com

David Abrahams wrote:
Simon Buchan <simon@hand-multimedia.co.nz> writes:
The good news is that most of the time, none of this matters much to you. If it complains, add the keyword and be thankful your compiler is conformant.
That policy might work okay for the average user, but it's not really appropriate for a library developer trying to write portable code.
Yes, in my original formatting, I explicitly said "If you want to write portable code", but don't we all?

On Oct 10, 2005, at 7:42 PM, Jared McIntyre wrote:
I've gone through the documentation, and I'm still unable to get this particular aspect of serialization working. I have two objects 'a' and 'b', and 'b' inherits from 'a'. I have a vector of 'a' pointers that may just be 'a' or may be 'b'. I've preregistered 'b', right before the vector serialization occurs, so that the serialization system should properly recognize that 'b' inherits from 'a'. However, only the 'a' pieces of each 'b' in the vector serializes.
Do your classes have virtual destructors or other virtual member functions? If not, I believe the serialization library cannot deduce the derived type. Matthias
participants (7)
-
David Abrahams
-
Jared McIntyre
-
Matthias Troyer
-
Robert Ramey
-
Simon Buchan
-
Stefan Seefeld
-
troy d. straszheim