Задача «Сериализация/десериализация»

Реализовать фреймворк для бинарной сериализации и десериализации произвольных структур данных.

Основа фреймворка приведена ниже:

// serialize.h
#pragma once

#include <iostream>
#include <iterator>
#include <algorithm>

template <typename T>
struct serializer {
    static void apply(const T &obj, std::ostream &os) {
        const uint8_t *ptr = reinterpret_cast<const uint8_t *>(&obj);

        std::ostream_iterator<uint8_t> oi(os);

        std::copy(ptr, ptr + sizeof(T), oi);
    }
};

///////////////////////////////////////////////////////////////////////

template <typename T>
struct deserializer {
    static void apply(T &val, std::istream &is) {
        uint8_t *ptr = reinterpret_cast<uint8_t*>(&val);
        std::istream_iterator<uint8_t> ii(is);

        std::copy_n(ii, sizeof(T), ptr);
    }
};

///////////////////////////////////////////////////////////////////////

template <typename T>
void serialize(const T &obj, std::ostream &os)
{
    serializer<T>::apply(obj, os);
}

template <typename T>
void deserialize(T &obj, std::istream &is)
{
    return deserializer<T>::apply(obj, is);
}

Данный код позволяет сериализовывать и десериализовывать любые примитивные объекты, как показано в примере:

// test_serialize.cpp
#include <fstream>
#include <iostream>
#include "serialize.h"

using namespace std;

int main()
{
    ofstream ofs("test.ser", ofstream::out | ofstream::binary);

    char hello[7] = "hello!";
    int boo[3] = { 1, 2, 3 };

    serialize(hello, ofs);
    serialize(boo, ofs);

    char hello2[7];
    int boo2[3];

    ofs.close();

    ifstream ifs("test.ser", ifstream::in | ofstream::binary);
    ifs >> noskipws;

    deserialize(hello2, ifs);
    deserialize(boo2, ifs);

    if (equal(hello, hello + 7, hello2))
        cout << "Hello OK!" << endl;

    if (equal(boo, boo + 3, boo2))
        cout << "Boo OK!" << endl;

    return 0;
}

Требуется расширить поведение serialize и deserialize, чтобы они поддерживали сериализацию и десериализацию стандартных классов и контейнеров:

  • std::string.
  • vector<T> для любого сериализуемого типа T.
  • map<K, V> для любых сериализуемых типов K, V.