c++serializationboostboost-serialization

Why does boost::serialize not work despite everything seeming right? ("unregistered class")


I am wondering about this. I have a C++ program with a number of data structs which derive from a common root and I need to serialize them using Boost. Each one has an inline member function to accept a visitor (so I can visit the structure without a "switch" statement).

The objects look like this:

In the .h file:

// Graphic component.
struct GraphicComponent : public Component {
  ... data members ...
  void accept(ComponentVisitor &vis) { vis.visitGraphicComponent(*this); }

 private:
  // Serialization routine.
  friend class boost::serialization::access;

template<class Archive>
  void serialize(Archive &a, const unsigned int v);
};
BOOST_CLASS_EXPORT_KEY(GraphicComponent)

// Position component.
struct PositionComponent : public Component {
  ... data members ...
  void accept(ComponentVisitor &vis) { vis.visitPositionComponent(*this); }

 private:
  // Serialization routine.
  friend class boost::serialization::access;

template<class Archive>
  void serialize(Archive &a, const unsigned int v);
};
BOOST_CLASS_EXPORT_KEY(PositionComponent)

...

In the .cpp file, I declare the "serialize" routines:

BOOST_CLASS_EXPORT_IMPLEMENT(GraphicComponent)
BOOST_CLASS_EXPORT_IMPLEMENT(PositionComponent)
...

template<class Archive>
  void GraphicComponent::serialize(Archive &a, const unsigned int v)
  {
    a & boost::serialization::base_object<Component>(*this);
    ... serialize data members ...
  }

template<class Archive>
  void PositionComponent::serialize(Archive &a, const unsigned int v)
  {
    a & boost::serialization::base_object<Component>(*this);
    ... serialize data members ...
  }

...

I also include the Boost archive through a common header. As far as I can tell, everything looks right. There's also a "BOOST_SERIALIZATION_ASSUME_ABSTRACT" on the base Component, as "accept" is pure virtual.

When I run the program and get to the point where it serializes this stuff, I get

 what():  unregistered class - derived class not registered or exported

Serialization occurs through a pointer to the base Component.

I've heard troubles involving Boost serialization and "libraries". The build system I was using, CMake, is set up to compile the program by assembling its subcomponents into libraries and then putting those together into a single executable to make the final program. Could that be the problem?

Also, Component derives from std::enable_shared_from_this (that's C++11 STL, not Boost) -- could this be the problem? If so, what can be done about it?


Solution

  • This is a partial answer as it doesn't explain exactly why it failed. I have managed to solve the problem by compiling the program as a single program instead of a bunch of libraries that are then statically linked together, which is how I thought I had to do it with the build system I was using since the documentation that was available online for the system was terse and when I put together the makefiles, I wasn't sure exactly how to do it. I suspect it has something to do with Boost's trouble dealing with this kind of code in libraries.