Can't get C++ Boost Pointer Serialization to work

Tony Camuso

This question is not the same as the one listed as duplicate: Boost c++ serializing a char * I am not using shared_ptr, and I have full access to the internals of my classes.

The closest response I could find was in Store a vector of pointers to custom objects to file which I found by searching for the compiler error.

However, the answer given there was not clear, at least not to me. It points back to the boost docs, which indicate that the simple code I have listed here should work. After cataloguing all the housekeeping that goes into serializing objects by pointer, the boost docs say this.

This serialization library addresses all of the above considerations.

If I must write a char[] one character at a time, or if I must dereference all pointer objects in a container and break them down to their constituent POD parts, writing their sizes in bytes to the stream first, in order to serialize with boost, then there doesn't seem to be much point in using boost. That's the lion's share of the work. Creating a text output stream and squirting bytes into it is trivial.

I'm not above saying that I may have a reading comprehension issue with the docs, but from my understanding of what I've read, the code snippet below should work. However, this code emits the following compiler error. So, I must be omitting something, but I just can't see it, so that's why I'm asking for help.

How about simply pointing out the failure point in the code snippet below? Or, even better, providing a snippet that does work?

/usr/include/boost/serialization/access.hpp:118:9: error: ‘class boost::ptr_vector<std::basic_string<char> >’ has no member named ‘serialize’
         t.serialize(ar, file_version);
         ^
#include <fstream>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>

class A {
public:
        A(){}

        char c;
        char *name;

        friend boost::serialization::access;
        template<class Archive>

        void serialize(Archive& ar, unsigned version) 
        {
                ar &  name;
        }
};

main()
{
        A a;
        a.name = (char *)"this is a test";

        std::ofstream ofs("table.txt");
        boost::archive::text_oarchive os(ofs);
        os << a;
}

I can serialize int, char, even STL types, but I cannot serialize anything with a pointer. For example, I can serialize std::vector<std::string>, but if I attempt to serialize std::vector<std::string *>, I will get the compiler error.

sehe

If I must write a char[] one character at a time, or if I must dereference all pointer objects in a container and break them down to their constituent POD parts, writing their sizes in bytes to the stream first, in order to serialize with boost, then there doesn't seem to be much point in using boost.

Yes. But you're trying to serialize a pointer. What should a pointer to char be serialized as? Surely T* should serialize a dynamically allocated T, no? So you would expect to serialize a single char unless name were nullptr?

Or do you expect to get full object tracking for each character serialized?

The whole point here is that you chose a raw pointer to a primitive type. The pointer lacks the necessary information. Hence, the onus is on you to add the information. If you find that tedious, you're free to use C++ types instead.

Note, by the way, that this is not legal in C++03 and up anyways:

a.name = (char *)"this is a test";

A static cast from char const(&)[15] to char * would drop a const qualification. Your compiler should reject this code anyways.

Here's my take on it (use std::string):

#include <boost/serialization/string.hpp>
#include <boost/archive/text_oarchive.hpp>

class A {
  public:
    std::string name;
    template <class Archive> void serialize(Archive &ar, unsigned) {
        ar & name;
    }
};

int main() {
    A a { "this is a test" };
    boost::archive::text_oarchive os(std::cout);
    os << a;
}

Incidentally, the linked duplicate question's title exactly matches what you're trying to do here: Boost c++ serializing a char * and the accepted answer displays exactly the same solution.

If you really insist, you can of course go mud-wrestle some C-style code for no glory:

#include <boost/serialization/serialization.hpp>
#include <boost/serialization/binary_object.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <cstring>
#include <cstdlib>

class A {
  public:
    A(char const* sz = nullptr) : name(sz? strdup(sz) : nullptr) {}
    A(A const&) = delete;
    A& operator=(A const&) = delete;

    ~A() { free(name); }

  private:
    char* name;

    template <class Archive> void save(Archive &ar, unsigned) const {
        bool have_name = name;
        ar & have_name;

        if (have_name)
        {
            size_t len = strlen(name);
            ar & len;
            ar & boost::serialization::make_binary_object(name, len);
        }
    }

    template <class Archive> void load(Archive &ar, unsigned) {
        bool have_name = name;
        ar & have_name;

        if (!have_name)
        {
            free(name);
            name = nullptr;
        } else
        {
            size_t len = 0;
            ar & len;

            name = static_cast<char*>(realloc(name, len));
            ar & boost::serialization::make_binary_object(name, len);
        }
    }

    friend class boost::serialization::access;
    BOOST_SERIALIZATION_SPLIT_MEMBER()
};


int main() {
    A a { "this is a test" };
    boost::archive::text_oarchive os(std::cout);
    os << a;
}

But all this gains you is 6x as much code, crippled value semantics, completely abandoned separation of concerns, a lot of bug potential (did you think of the difference between having name==null and strlen(name)==0? Currently my implementation employs unspecified (implementation-defined) behaviour. I'll leave it as an exercise to you, the reader, to come up with airtight handling here) and... not even readable string output.

Yes, of course make_array would give you 14 116 104 105 115 32 105 115 32 97 32 116 101 115 116 instead of dGhpcyBpcyBhIHRlc3Q=, but that's horrifically storage inefficient and still not human readable.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

Can't get C++ Boost Pointer Serialization to work

From Dev

how to get boost::serialization to work?

From Dev

Can't get BOOST odeint to work with Adams-Bashforth-Moulton

From Dev

Boost serialization doesn't work with shared_ptr<int>

From Dev

can't deserialize with boost::serialization and shared_ptr

From Dev

Copies of a pointer into a pointer doesn't work in C

From Dev

Get private data members for non intrusive boost serialization C++

From Dev

Pointer can't get data

From Dev

Boost serialization of pointer saves hexadecimal value of pointer not the contents of the object

From Dev

boost serialization vector in c++

From Dev

Boost binary serialization doesn't work occasionally. The parsed data is corrupted sometimes

From Dev

Boost binary serialization doesn't work occasionally. The parsed data is corrupted sometimes

From Dev

Checking NULL Pointer In C Doesn't Work

From Dev

boost serialization of nested struct does not work

From Dev

C++ can't get regex_match to work

From Dev

Can't get parameters to work with OdbcConnection in C#

From Dev

Can't get math c++ program to work

From Dev

Can't get parameters to work with OdbcConnection in C#

From Dev

C++ can't get regex_match to work

From Dev

Can't Get Makefile to work

From Dev

Can't get regex to work

From Dev

Can't get setScrollVisible() to work

From Dev

Can't get virtualenvwrapper to work

From Dev

Can't get MapKit to work

From Dev

Can't Get Phaser To Work

From Dev

Can't get SendInput() to work

From Dev

Can't get OnTouchListner to work

From Dev

Can't get mysqldump to work

From Dev

can't get noUISlider to work