How to serialize basic_string<unsigned char>

I want to serialize an existing (low level) class which uses a `std::basic_string<unsigned char>' as member variable. Compiling the code (boost/serialization/string.hpp is included) fails with this message: /usr/include/boost/serialization/access.hpp:109: error: ‘class std::basic_string<unsigned char, std::char_traits<unsigned char>, std::allocator<unsigned char> >’ has no member named ‘serialize’ As I understand, std::string is now treated as a simple data type, but std:basic_string<unsigned char> is not. Is there already existing support for such instanciations of std::basic_string? Any hint on what I can do to get this working? Cheers, M'bert -- ----------- / http://herbert.the-little-red-haired-girl.org / ------------- =+= Warum geht ein Bratscher nicht �ber einen Friedhof? Zu viele Kreuze...

Martin Dietze wrote:
I want to serialize an existing (low level) class which uses a `std::basic_string<unsigned char>' as member variable. Compiling the code (boost/serialization/string.hpp is included) fails with this message:
/usr/include/boost/serialization/access.hpp:109: error: 'class std::basic_string<unsigned char, std::char_traits<unsigned char>, std::allocator<unsigned char> >' has no member named 'serialize'
As I understand, std::string is now treated as a simple data type, but std:basic_string<unsigned char> is not. Is there already existing support for such instanciations of std::basic_string? Any hint on what I can do to get this working?
Just look at boost/serialization/string.hpp and do the same thing for unsigned char Robert Ramey

On Sat, April 10, 2010, Robert Ramey wrote:
Just look at boost/serialization/string.hpp and do the same thing for unsigned char
Yes, that was my first thought, too. Consider the code below. Execution fails with this assertion: a.out: test.cc:47: void load(): Assertion `size == 10' failed. Aborted I also tried the collection-based approach which is currently commented out in serialization/string.hpp, but this does not compile since basic_string<> does not have a back() method. -------------------- SNIP ----------------------- #include <string> #include <fstream> #include <cassert> #include <boost/archive/binary_oarchive.hpp> #include <boost/archive/binary_iarchive.hpp> BOOST_CLASS_IMPLEMENTATION(std::basic_string<unsigned char>, boost::serialization::primitive_type) #define SIZE 10 #define FNAME "/tmp/archive.ser" class A { public: std::basic_string<unsigned char> m_string; private: friend class boost::serialization::access; template<class Archive> void serialize (Archive & ar, const unsigned int version) { ar & m_string; } }; void save (void) { A a; a.m_string.assign (SIZE, (unsigned char)0); for (int i = 0; i < SIZE; ++i) { a.m_string[i] = (unsigned char)i; } std::ofstream ofs (FNAME, std::ios::out | std::ios::binary); boost::archive::binary_oarchive oa (ofs); oa << a; } void load (void) { A b; std::ifstream ifs (FNAME, std::ios::in | std::ios::binary); boost::archive::binary_iarchive ia (ifs); ia >> b; size_t size = b.m_string.size (); assert (size == SIZE); for (int i = 0; i < b.m_string.size (); ++i) { assert ((int)b.m_string[i] == i); } } int main (void) { save (); load (); return 0; } -------------------- SNIP ----------------------- Cheers, M'bert -- ----------- / http://herbert.the-little-red-haired-girl.org / ------------- =+= while (!asleep) ++sheep;

Martin Dietze wrote:
On Sat, April 10, 2010, Robert Ramey wrote:
Just look at boost/serialization/string.hpp and do the same thing for unsigned char
Yes, that was my first thought, too. Consider the code below. Execution fails with this assertion:
a.out: test.cc:47: void load(): Assertion `size == 10' failed. Aborted
This is a little bit tricky. Look carefully at the documentation regarding BOOST_CLASS_IMPLEMENTATION and try replacing BOOST_CLASS_IMPLEMENTATION(std::basic_string<unsigned char>, boost::serialization::primitive_type) with BOOST_CLASS_IMPLEMENTATION(std::basic_string<unsigned char>, boost::serialization::object_type) (double check "object_type") Basically you want the next level of support above primitive_type. Also, consider using ar & static_cast<basic_string<char> >(my unsigned string) Robert Ramey

On Sat, April 10, 2010, Robert Ramey wrote:
BOOST_CLASS_IMPLEMENTATION(std::basic_string<unsigned char>, boost::serialization::primitive_type) with BOOST_CLASS_IMPLEMENTATION(std::basic_string<unsigned char>, boost::serialization::object_type)
(double check "object_type") Basically you want the next level of support above primitive_type.
... which turns out to be `object_serializable' (Serialize the objects of this type using the objects "serialize" function or template. This permits values to be written/read to/from archives but includes no class or version information).
Also, consider using
ar & static_cast<basic_string<char> >(my unsigned string)
This does not compile, obviously there is no way to simply assign one to another. Having used `object_serializable' instead of `primitive_type' (same for `object_class_info') got me back to the original problem, since there's no builtin `serialize' method for this class. Cheers, M'bert -- ----------- / http://herbert.the-little-red-haired-girl.org / ------------- =+= Ed, the greatest WYGIWYG editor of all.

As a workaround the code below works. However this solution is only possible because <char> and <unsigned char> can be assigned like this. I'd still be interested to learn how to do this without ugly code like this... ------------------------ SNIP ------------------------- BOOST_CLASS_IMPLEMENTATION(std::basic_string<unsigned char>, boost::serialization::primitive_type) class A { public: std::basic_string<unsigned char> m_string; private: friend class boost::serialization::access; template<class Archive> void save (Archive & ar, const unsigned int version) const { std::basic_string<char> s; s.assign (m_string.size (), (char)0); for (int i = 0; i < m_string.size (); ++i) { s[i] = (char)m_string[i]; } ar & s; } template<class Archive> void load (Archive & ar, const unsigned int version) { std::basic_string<char> s; ar & s; m_string.assign (s.size (), (unsigned char)0); for (int i = 0; i < s.size (); ++i) { m_string[i] = (unsigned char)s[i]; } } BOOST_SERIALIZATION_SPLIT_MEMBER() }; ------------------------ SNIP ------------------------- M'bert -- ----------- / http://herbert.the-little-red-haired-girl.org / ------------- =+= It was hard to code, so it should be hard to understand!

Martin Dietze wrote:
On Sat, April 10, 2010, Robert Ramey wrote:
BOOST_CLASS_IMPLEMENTATION(std::basic_string<unsigned char>, boost::serialization::primitive_type) with BOOST_CLASS_IMPLEMENTATION(std::basic_string<unsigned char>, boost::serialization::object_type)
(double check "object_type") Basically you want the next level of support above primitive_type.
... which turns out to be `object_serializable' (Serialize the objects of this type using the objects "serialize" function or template. This permits values to be written/read to/from archives but includes no class or version information).
Also, consider using
ar & static_cast<basic_string<char> >(my unsigned string)
This does not compile, obviously there is no way to simply assign one to another.
Having used `object_serializable' instead of `primitive_type' (same for `object_class_info') got me back to the original problem, since there's no builtin `serialize' method for this class.
But now you can define an non member serialize template for you "new" type. Robert Ramey
Cheers,
M'bert
participants (2)
-
Martin Dietze
-
Robert Ramey