Opened 13 years ago
Closed 13 years ago
#4026 closed Feature Requests (wontfix)
Request to trap missing serialize method in derived class(es)
Reported by: | Richard Hazlewood | Owned by: | Robert Ramey |
---|---|---|---|
Milestone: | Boost 1.43.0 | Component: | serialization |
Version: | Boost 1.42.0 | Severity: | Problem |
Keywords: | serialize version derived missing | Cc: |
Description
Is there a way the serialization library can trap (or warn of) accidental serialization of a derived class, where the implementor has not added a serialize method for the derived class?
The "Base Classes" section of the documentation says:
"For this reason, all serialize member functions should be private."
However, this does not help (at least for MSVC71) for cases where the serialize method is completely missing in the derived class; the derived class is implicitly converted to the base (is-a).
This case can easily be missed, and results in invalid data as soon as versioned data is added to the base class. This is demonstrated in the example code, below.
I don't know if it can be achieved, but at the point of serialization, where the library knows the type that is being serialized, it would be useful if it could warn if the serialize method being called was not a member of the *exact* type (clearly only for class types). If the call is falling through to the base then it is probably (always?) an oversight.
Perhaps if there was a class sitting between 'Base' and 'Derived' then that may be a case for not wanting the warning, but it seems like good practice to add the serialize method anyway.
If a warning message is unsuitable, then it would useful to have a documentation update along the lines of:
If there is any chance of using polymorphism or changing the version of a class then ensure all derived classes implement the serialize method, making the base_object<> call at a minimum.
#include <boost/archive/text_oarchive.hpp> #include <boost/serialization/serialization.hpp> #include <boost/serialization/base_object.hpp> #include <sstream> class Base { private: friend class boost::serialization::access; template <typename A> void serialize(A &/*a*/, const unsigned v) { assert(v == 1); // Uh-oh, we're picking up version of 'Derived' } }; BOOST_CLASS_VERSION(Base, 1); class Derived : public Base { // Implementor 'forgets' to add: // template <typename A> // void serialize(A &a, const unsigned v) // { // a & boost::serialization::base_object<Base>(*this); // } }; int main(int, char *[]) { std::ostringstream ostr; boost::archive::text_oarchive oa(ostr); Derived d; // Ideally we should be forced to: // Base &b = d; // oa & b; // if no serialize method is found for 'Derived' oa & d; return 0; }
I like this idea, but I couldn't figure out a way to implement it. If you think of one, let me know. BTW, if you use
your program will trap. Maybe that fact might be useful.
Robert Ramey