[Boost-users] Serialization of template classes via base

709 views
Skip to first unread message

Bruno Martínez

unread,
Sep 8, 2005, 12:29:41 AM9/8/05
to boost...@lists.boost.org
Hi.

This has been asked before here
http://lists.boost.org/boost-users/2005/05/11706.php
but I didn't understand the workaround.

What I want is to serialize class B where

class A {
...
};

template<...>
class B : public A {
...
};

when I have an A*.

The workarounds proposed were using RTTI non portably, or registering the
classes each time. How would such solution look like?

Regards,
Bruno

_______________________________________________
Boost-users mailing list
Boost...@lists.boost.org
http://lists.boost.org/mailman/listinfo.cgi/boost-users

Robert Ramey

unread,
Sep 8, 2005, 3:37:03 AM9/8/05
to boost...@lists.boost.org
Hmm - I the referenced email referred to shared_ptr. Your case is covered
in the documenation. Reference/Serializable/Pointers.

Robert Ramey

Bruno Martínez

unread,
Sep 8, 2005, 9:16:49 AM9/8/05
to boost...@lists.boost.org
On Thu, 08 Sep 2005 04:37:03 -0300, Robert Ramey <ra...@rrsd.com> wrote:

> Hmm - I the referenced email referred to shared_ptr.

The link's mail's subjects was
Serialize templates classes > automatique exportdeclaration
. I didn't get the part about it referring to shared_ptr.

> Your case is covered
> in the documenation. Reference/Serializable/Pointers.

The problem is that I never know a priori the instantiations of the B
template class present in a program, so I can't register them all. My use
case is a boost::function like class, where type erasure is a must. It's
very difficult to register a bind result type. Do you understand me now?

Thank you,

Andreas Huber

unread,
Sep 8, 2005, 11:47:59 AM9/8/05
to boost...@lists.boost.org
Robert Ramey <ramey <at> rrsd.com> writes:
> Hmm - I the referenced email referred to shared_ptr. Your case is covered
> in the documenation. Reference/Serializable/Pointers.

I think it is not. AFAICT what Bruno needs, is a way to *automatically*
register all instantiations of a given template. As I have recently discovered
I would have the same need when I want to add serialization to
boost::statechart::state_machine<>.

>From the documentation it seems that what the serialization library currently
supports is a way to register a type at *namespace* scope. That is, if I have
a template ...

class A {};

template< class T >
class B
{
};

... I need to *manually* register all instantiations of B, e.g. as follows:

BOOST_CLASS_EXPORT_GUID( B< int > );
BOOST_CLASS_EXPORT_GUID( B< char > );
BOOST_CLASS_EXPORT_GUID( B< double > );
BOOST_CLASS_EXPORT_GUID( B< float > );

For a library containing B's definition, sometimes you can get away with
requiring users to manually register all instantiations but often even the
users cannot know all instantiations because B is an implementation detail of
the library.

IIRC, registration within load/save (with register_type<>) is not an option,
as that would be too late.

--
Andreas Huber

When replying by private email, please remove the words spam and trap
from the address shown in the header.

Robert Ramey

unread,
Sep 8, 2005, 11:58:37 AM9/8/05
to boost...@lists.boost.org
OK - I think I understand you now.

a) we don't know all the derived classes so we can't use "register"
b) BOOST_CLASS_EXPORT doesn't work with templates.
c) An attempt to use the underlying defintion of BOOST_CLASS_EXPORT fails
because each class needs its own distinct name and we don't have a portable
way of automatically generating something like:

"my_class<int>" from class<T> when T == int

So we have to make a new export invocation by hand for each template
instantiation. This gets us back to square one in that we don't know
apriori all the types that will be used as template parameters.

I don't have a general solution for this.

In the longer term it might be solvable in general. This problem has been
discussed in some detail from time to time. In the shorter term you could
probably craft a solution that would not be a general solution but might
work in some cases. If you don't care about archive portability - that is
if your only loading archives with the same compiler (and probably standard
library), you could craft something which would generate a uniquename from
type_id.


Robert Ramey

Bruno Martínez wrote:

Bruno Martínez

unread,
Sep 9, 2005, 12:12:21 PM9/9/05
to boost...@lists.boost.org
On Thu, 08 Sep 2005 12:58:37 -0300, Robert Ramey <ra...@rrsd.com> wrote:

> OK - I think I understand you now.
>
> a) we don't know all the derived classes so we can't use "register"
> b) BOOST_CLASS_EXPORT doesn't work with templates.
> c) An attempt to use the underlying defintion of BOOST_CLASS_EXPORT fails
> because each class needs its own distinct name and we don't have a
> portable
> way of automatically generating something like:
>
> "my_class<int>" from class<T> when T == int
>
> So we have to make a new export invocation by hand for each template
> instantiation. This gets us back to square one in that we don't know
> apriori all the types that will be used as template parameters.

Maybe this would be possible if we could ask the serialization lib itself
for info about int. Two classes my_class<T1> and my_class<T2> would be
ordered the same way than T1 and T2 are. It would be like subregistration.

> I don't have a general solution for this.
>
> In the longer term it might be solvable in general. This problem has
> been
> discussed in some detail from time to time.

Could you please find the links to these conversations? I've been
unsuccesful.

> In the shorter term you could
> probably craft a solution that would not be a general solution but might
> work in some cases. If you don't care about archive portability - that
> is
> if your only loading archives with the same compiler (and probably
> standard
> library), you could craft something which would generate a uniquename
> from
> type_id.

This is the route that I'm going to take. I'll try to understand how the
underlyings of BOOST_CLASS_EXPORT work.

Regards,
Bruno Martínez

Robert Ramey

unread,
Sep 9, 2005, 2:43:58 PM9/9/05
to boost...@lists.boost.org
if that's what you want to do - don't look too deeply into export.hpp.

The key macro is BOOST_CLASS_EXPORT_GUID(class, "name) and

BOOST_CLASS_EXPORT(T) is just

#define BOOST_CLASS_EXPORT(T) BOOST_CLASS_EXPORT_GUID(T, "T") // sort of

So the best would be for you to make something like:

template<class T>
const char * name_from_type<T>()

so one could say BOOST_CLASS_EXPORT_GUID(T, name_from_type<T>)

That is, the idea of an automatically generated unique string which
identifies a class would be useful in lots of areas besides serialization.
If you could generate a portable one - you'd be famous. If it were easy I
would have done it. In anycase its an orthogonal question to the
serialization library.

Good luck.

Robert Ramey

Bruno Martínez

unread,
Sep 11, 2005, 6:14:14 PM9/11/05
to boost...@lists.boost.org
On Fri, 09 Sep 2005 15:43:58 -0300, Robert Ramey <ra...@rrsd.com> wrote:

> if that's what you want to do - don't look too deeply into export.hpp.
>
> The key macro is BOOST_CLASS_EXPORT_GUID(class, "name) and
>
> BOOST_CLASS_EXPORT(T) is just
>
> #define BOOST_CLASS_EXPORT(T) BOOST_CLASS_EXPORT_GUID(T, "T") // sort of
>
> So the best would be for you to make something like:
>
> template<class T>
> const char * name_from_type<T>()

You meant this, right?:

template<class T>
const char * name_from_type()/*<T>*/ {
}

> so one could say BOOST_CLASS_EXPORT_GUID(T, name_from_type<T>)

I don't understand how BOOST_CLASS_EXPORT_GUID would work that way. There
has to be a call to this macro for each type, and all calls have to be at
global scope.

What I have now is:

template<class T>
const char * name_from_type()
{
return typeid(T).name();
}

struct base {
template<class Archive>
void serialize(Archive&, unsigned) {
}
virtual ~base() {}
};

template<class T>
struct registor {
registor();
};

template<class T>
struct derived : base {
T t;
derived(T t) : t(t) {
boost::serialization::type_info_implementation<derived<T> >::
type::export_register(name_from_type<derived<T> >());
boost::archive::detail::export_impl::for_each_archive<boost::
archive::detail::known_archive_types::type, derived<T> >::
instantiate();
}
template<class Archive>
void serialize(Archive& ar, unsigned) {
ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(base);
ar & BOOST_SERIALIZATION_NVP(t);
}
static registor<T> reg;
};

template<class T>
registor<T>::registor() {
boost::serialization::type_info_implementation<derived<T> >::
type::export_register(name_from_type<derived<T> >());
boost::archive::detail::export_impl::for_each_archive<boost::
archive::detail::known_archive_types::type, derived<T> >::
instantiate();
}

template<class T>
registor<T> derived<T>::reg;

However, possible interactions with the linker, etc., make me nervous
about this solution. The serialization lib takes precautions, but going
this deep into export.hpp implementation bypasses them all. Can
BOOST_CLASS_EXPORT_GUID be used after all for this? Is there a better way
to do this?

With the Itanium ABI making it's way into gcc, the typeinfo::name hack
doesn't look so bad. It would be great if hooking export this way were
easier.

Thanks,
Bruno

Robert Ramey

unread,
Sep 12, 2005, 12:42:34 AM9/12/05
to boost...@lists.boost.org
Bruno Martínez wrote:
>> so one could say BOOST_CLASS_EXPORT_GUID(T, name_from_type<T>)
>
> I don't understand how BOOST_CLASS_EXPORT_GUID would work that way.
> There has to be a call to this macro for each type, and all calls
> have to be at global scope.
>

Actually I envisioned that the text "name_from_type..." would be passed into
the code and be invoked at each place - but maybe that was overly
optimistic. I would like to see name from type be orthogonal to export.hpp
which due to a number off issues (template instantitiation and linker
behavior and...) is pretty complex.

You might try to make something that looks like:

BOOST_TEMPLATE_EXPORT(template name)

But I haven't thought about it much after I considered it had a lot of
issues.

BTW - don't forget to consider namespaces of types and the fact that a
header module might be included in different header modules in different
namespaces. Or maybe not. I believe that this problem is not really
solvable in a definitive way at this time. But good luck.

Robert Ramey



Reply all
Reply to author
Forward
0 new messages