|
Serialization - Serialization WrappersBoost , ,

|
Serialization
Serialization Wrappers
|
- Binary Objects
- Arrays
BOOST_STRONG_TYPEDEF
- Collection Sizes
- Name-Value Pairs
- Composition
Sometimes it convenient to create a temporary object just to support serialization
of some underlying data. This permits an archive class to define special
handling of this type. The library includes several such types for varying
purposes.
Некоторые архивы требуют особого обращения с обертками, и, следовательно,<is_wrapper >Для этих классов обертки характерна истина. Бинарный объект — это просто последовательность байтов, хранящихся в виде необработанных двоичных данных. Это, скорее всего, будет использоваться для большого количества данных «легкого веса», таких как карта пикселей или встроенный двоичный файл. Файл заголовкаbinary_object.hppвключает конструкторы:<
boost::serialization::binary_object(void * t, size_t size);
boost::serialization::make_binary_object(void * t, size_t size);
>, который сконструирует временный двоичный объект, который может быть сериализован, как и любой другой объект. Сериализация по умолчанию заключается в использовании примитивов архивного класса<save_binary >и<load_binary >. Обратите внимание, что он не выделяет никакого хранилища или не создает никаких объектов. Его единственная цель - передать размер данных и адрес в виде пары в класс архива.Массив представляет собой непрерывную последовательность однородных типов данных, таких как встроенный C-массив,<boost::array<T> >или<std::vector<T> >. Целью этой обертки является поддержка типов архивов (таких как бинарные архивы), которые обеспечивают оптимизированную сериализацию для смежных последовательностей объектов того же типа. Файл заголовкаarray.hppвключает в себя функцию<
template <T>
boost::serialization::make_array(T* t, std::size_t size);
>, которая будет создавать временный<array >объект<
template
class array
{
public:
typedef T value_type;
array(value_type* t, std::size_t s);
value_type* address() const;
std::size_t count() const;
};
>, который может быть сериализован, как и любой другой объект. Сериализация по умолчанию - это сериализация каждого элемента массива. Обратите внимание, что он не выделяет никакого хранилища или не создает никаких объектов. Его единственной целью является передача типа данных, размера и адреса в класс архива. Архивные типы, которые могут обеспечить оптимизированные реализации для смежных массивов однородных типов данных, должны перегружать сериализацию<array >.Другой пример обертки для сериализации —.<BOOST_STRONG_TYPEDEF >Шаблон. Библиотеки сериализации используют их для передачи определенных видов целых чисел, таких как object_id, версия и т. д., в класс архива. Учитывая, что эти целые числа теперь различимы в соответствии с их типом, XML-архивы могут применять специальную обработку к этим типам. Например, номер версии отображается как атрибут XML в форме «версия=12». При отсутствии какого-либо конкретного переопределения эти типы автоматически преобразуются в основной целочисленный тип, поэтому специальные переопределения, используемые для XML-архивов, не нужны для других архивов.Примером сильного typedef является<collection_size_type >в файле заголовкаcollection_size_type.hpp. Этот тип следует использовать для сериализации размера коллекции C++, чтобы архив мог выбрать наилучшее интегральное представление для сериализации размеров коллекции. Это необходимо, поскольку, хотя<std::size_t >гарантированно является интегральным типом, достаточно большим, чтобы представлять размер коллекции на конкретной платформе, архив может захотеть сериализовать размер иначе, чем этот тип. Например,<collection_size_type >может быть сериализован как целое число переменной длины в переносном двоичном архиве.XML-архивы представляют собой несколько особый случай. XML-формат имеет вложенную структуру, которая хорошо отображает шаблон «рекурсивный посетитель класса», используемый системой сериализации. Однако XML отличается от других форматов тем, что для каждого элемента данных класса требуется имя. Наша цель состоит в том, чтобы добавить эту информацию в спецификацию сериализации класса, при этом позволяя использовать код сериализации с любым архивом.Наше решение состоит в том, чтобы обернуть членов класса, которые будут сериализованы вименно-значной паре. Эта структура определена вnvp.hpp. Это просто ссылка на элемент данных в сочетании с указателем на<const char * >, который соответствует имени XML. Он реализует функции сериализации по умолчанию для пары имени-значения. Это действие по умолчанию заключается в том, чтобы просто игнорировать имя элемента и сериализовать значение данных обычным способом. Для классов архивов, которые не содержат специального положения для пар имён-значений, это действие, которое будет вызываться при сериализации пары имён-значений. Следовательно, обертывание значения данных в пару имён-значений не будет иметь никакого эффекта при использовании с архивами, которые не содержат специального положения для этой обертки. Классы архивов xml содержат код, аналогичный:<
// special treatment for name-value pairs.
template<class T>
xml_oarchive & operator&(const boost::serialization::nvp& t)
{
// write an xml start tag
start_tag(t.name());
// serialize the data as usual
*this & t.value();
// write an xml end tag
end_tag(t.name());
}
>Самое очевидное и удобное имя, которое можно назвать именем элемента данных XML, - сюрприз! - имя члена данных класса C++. Таким образом, наш код сериализации будет выглядеть так:<
ar & make_nvp("my_variable", my_variable);
>Чтобы упростить набор текста и повысить читаемость, определен макрос, чтобы мы могли написать:<
ar & BOOST_SERIALIZATION_NVP(my_variable);
>Аналогично существует макро-определение, которое позволяет нам писать:<
BOOST_SERIALIZATION_BASE_OBJECT_NVP(my_base_class)
>Обратите внимание, что эти макросы должны использоваться в пространстве имен класса и без квалификации пространства имен в аргументе.demo_gps.hppвключает в себя обертки NVP или все элементы данных.demo_xml.cppсохраняет и загружает данные в XML-архив.Здесьприведен пример XML-архива, соответствующий нашему учебному примеру. Обертки должны быть сконструированы так, чтобы их можно было составлять по мере необходимости. Например, для передачи двоичных данных в качестве пары значений имени используют:<
ar & make_nvp("named_binary_object", make_binary_object(address, size));
> |