[serialization] Proposal to add support for lexical_cast

Hi, I propose the addition of a lexical_cast wrapper to Boost.Serialization. Motivating example: Suppose you have several UDTs for which you already have defined insertion/extraction operators, and you want to use Boost.Serialization to read/write values of these UDTs, preferably in a non-intrusive way. Problem: Boost.Serialization doesn't make use of existing insertion/extraction operators for the UDTs. Proposed addition: A Serialization Wrapper (similar to those described in http://tinyurl.com/e46v5 [1]) that performs on-the-fly conversion of an UDT value to some serializable type, usually a std::string. Code is attached. The proposed wrapper allows to specify a conversion that will be used during serialization/deserialization operations. During serialization, a value will get converted to a different type; the converted value is written to the archive. During deserialization, the value is converted back to the original type. The proposed wrapper uses boost::lexical cast for the conversion. Usage example: // udt.hpp struct udt { }; std::ostream &operator<<(std::ostream &, udt const &); std::istream &operator>>(std::istream &, udt const &); // someclass.hpp #include "udt.hpp" #include <boost/serialization.hpp> struct someclass { template<typename Archive> void serialize(Archive &ar, const unsigned int version) { ar & boost::serialization::lexical_cast<std::string>(my_udt); } private: udt my_udt; }; Pros: - very easy to use - non-intrusive Cons: - not very fast Questions: - Would you consider this a useful addition? - Would the name boost::serialization::lexical_cast be acceptable? - Do you see a use case for using an "external" type other than std::string with this wrapper, e.g ar & boost::serialization::lexical_cast<int>(my_udt); // ? (The code could be simplified, otherwise) - Similar wrappers could be written for the C++ cast operations, too. Would such wrappers be useful? - Would it be desirable to extend this to a general conversion-on-the-fly framework? - Assuming there are some positive responses about the usefulness of the lexical_cast wrapper, would this addition be suitable for a fast-track review (it is very tiny)? (I'd say no if this evolves into a general conversion-on-the-fly framework) - other comments? Thanks to Robert who helped me to understand my own code better. Regards, m [1] http://boost.org/libs/serialization/doc/wrappers.html // (C) Copyright Martin Wille 2005. Distributed under the Boost // Software License, Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_SERIALIZATION_LEXICAL_CAST_HPP #define BOOST_SERIALIZATION_LEXICAL_CAST_HPP #include <boost/lexical_cast.hpp> #include <boost/serialization/traits.hpp> #include <boost/serialization/split_member.hpp> namespace boost { namespace serialization { template <class T, class Intermediate = std::string> struct lexical_cast_wrapper : traits <lexical_cast_wrapper<T, Intermediate> ,object_serializable , track_never > { explicit lexical_cast_wrapper(T &t) : value(t) {} template <class Archive> void save(Archive &ar, unsigned int) const { Intermediate tmp((boost::lexical_cast<Intermediate>(value))); ar << tmp; } template <class Archive> void load(Archive &ar, unsigned int) const { Intermediate tmp; ar >> tmp; value = boost::lexical_cast<T>(tmp); } BOOST_SERIALIZATION_SPLIT_MEMBER(); private: T &value; }; template <class Intermediate, class T> lexical_cast_wrapper<T, Intermediate> lexical_cast(T &value) { return lexical_cast_wrapper<T, Intermediate>(value); } template <class T> lexical_cast_wrapper<T> lexical_cast(T &value) { return lexical_cast_wrapper<T>(value); } }} #endif

Martin Wille wrote:
Usage example:
// udt.hpp struct udt { }; std::ostream &operator<<(std::ostream &, udt const &); std::istream &operator>>(std::istream &, udt const &);
// someclass.hpp #include "udt.hpp" #include <boost/serialization.hpp>
struct someclass { template<typename Archive> void serialize(Archive &ar, const unsigned int version) { ar & boost::serialization::lexical_cast<std::string>(my_udt); }
private: udt my_udt; };
This puts the serialization support for udt at the wrong level. If you have twelve classes that have four udt members each, you'll have to repeat "boost::serialization::lexical_cast<std::string>()" 48 times. And vector<udt> will still not work. It's better to define load+save for udt. If you do that, you'll see that the proposed wrapper adds almost no value. The 'almost' part comes from track_never, which enables you to sidestep the usual problem of serializing temporaries. :-)
- Do you see a use case for using an "external" type other than std::string with this wrapper, e.g ar & boost::serialization::lexical_cast<int>(my_udt); // ?
I'm not sure I do.
- Assuming there are some positive responses about the usefulness of the lexical_cast wrapper, would this addition be suitable for a fast-track review (it is very tiny)?
Fast-track components need to already be in use as an implementation detail of an existing Boost library, I believe.

Peter Dimov wrote:
Martin Wille wrote:
Usage example:
// udt.hpp struct udt { }; std::ostream &operator<<(std::ostream &, udt const &); std::istream &operator>>(std::istream &, udt const &);
// someclass.hpp #include "udt.hpp" #include <boost/serialization.hpp>
struct someclass { template<typename Archive> void serialize(Archive &ar, const unsigned int version) { ar & boost::serialization::lexical_cast<std::string>(my_udt); }
private: udt my_udt; };
This puts the serialization support for udt at the wrong level. If you have twelve classes that have four udt members each, you'll have to repeat "boost::serialization::lexical_cast<std::string>()" 48 times. And vector<udt> will still not work.
It's better to define load+save for udt.
This wasn't the case for my code, which used each udt only once.
If you do that, you'll see that the proposed wrapper adds almost no value. The 'almost' part comes from track_never, which enables you to sidestep the usual problem of serializing temporaries. :-)
With the lexical_cast wrapper you can do: template <typename Archive> void serialize(Archive &ar, udt &my_udt, unsigned int version) { ar & boost::serialization::lexical_cast<std::string>(my_udt); } IMHO, this is still better than spelling out the load/save functions. Thanks for your comments, m Send instant messages to your online friends http://au.messenger.yahoo.com
participants (2)
-
Martin Wille
-
Peter Dimov