简体   繁体   中英

Serialize C++ object without knowing its fields

I'm trying to learn how to serialize C++ objects. After reading couple of posts here, it seems a nice idea to utilize boost serialization functions and archiving using load/save functions. However, I would like to avoid using boost library.

Conceptually, can I save an object without knowing its fields. With no reflection in C++, is the only way to store an object is to know all its class members.

Can using stringstream and overloading the << operator to convert an object to a string, can I directly save an object.

Thanks, K.

Conceptually, can I save an object without knowing its fields.

No, you can't.

With no reflection in C++, is the only way to store an object is to know all its class members.

Yes. The best way is to leave that knowledge encapsulated in that class itself:

 class MyClass {
 public:
     std::ostream& put(std::ostream& os) const {
         os << field1 << " " << field2 << std::endl;
         return os;
     }
     friend std::ostream& operator<<(std::ostream& os, const MyClass& myclass) {
         return myClass.put(os);
     }
 private:
     int field1;
     double field2;
 };

An approach you can follow is to support tuple-likes and iterables by default.

Have a read_archive and write_archive that first does fancy sfinae to detect types that support for(:) loops, and types that are tuple-like in that they support std::tuple_size and ADL get<I> .

This also lines up with one form of structured binding support in C++17.

Next, have a to_tie sfinae adl enabled based implementation, that checks to_tie() and to_tie(.) . If so and read/writable, uses that.

Maybe somewhere in there include an adl lookup of an archive_io function, so you can explicitly write your own io.

The goal is to auto-archive as much as possible, and what you cannot make it easy to compose with.

If you want to copy the object as it is like a true snapshot, we can read the bytes in the object one by one and store them as characters and paste them onto another object or save it in a file. This is a rough idea:

#include <iostream>
#include <iomanip>

struct Serialization
{
    std::string data;
    template <class T>
    void in(const T &obj)
    {
        auto size = sizeof(T);
        const char *ptr = (const char *)&obj;

        for (size_t i = 0; i < size; i++)
            data.push_back(*(ptr + i));
    }
    template <class T>
    void out(T &obj)
    {
        char *ptr = (char *)&obj;
        for (size_t i = 0; i < data.size(); i++)
            *(ptr + i) = data[i];
    }

    void clear() { data.clear(); }
};

We don't know what is inside the object, it just gets copied as it is. This is somehow easy to use because shallow-copies any object, but also not desirable when

  • There are pointer family members (raw pointers, smart pointers, std::vector,...) that own some memory out of the object. Only pointers are copied but the target memories won't be copied.

  • It also copies a class's vtable pointer which I don't know if it would be useful at all.

Examples:

class person
{
    int age;
    char name[3];
    float height;
public:
    person() = default;
    person(int a, char n[3], float h) : age{a}, height{h}
    {
        for (size_t i = 0; i < 3; i++)
            name[i] = n[i];
    }
    void print()
    {
        std::cout << age << " " << name[0] << name[1] << name[2] << " " << height << "\n";
    }
};

int main()
{
    char x[3] = {'1', '2', '3'};
    person m{12, x, 180};
    person n;
    Serialization s;
    s.in(m);
    s.out(n);
    n.print(); // 12 123 180

    s.clear();
    double d;
    s.in(1.2345678910);
    s.out(d);
    std::cout << std::setprecision(10) << d; // 1.234567891

    return 0;
}

The Serialization class can be extended to serialize multiple identical/different objects by putting some conversions for writing strings, like repetitions of

 object name size => object name => object data size => object data

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM