Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
Разработка программного обеспечения

Serialization - Class Serialization Traits

Boost , ,

C++ Boost

Serialization

Class Serialization Traits


Version
Implementation Level
Object Tracking
Export Key
Abstract
Type Information Implementation
Wrappers
Bitwise Serialization
Template Serialization Traits
Compile Time Warnings and Errors
Serialization of data depends on the type of the data. For example, for primitive types such as int, it wouldn't make sense to save a version number in the archive. Likewise, for a data type that is never serialized through a pointer, it would (almost) never make sense to track the address of objects saved to/loaded from the archive as it will never be saved/loaded more than once in any case. Details of serialization for a particular data type will vary depending on the type, the way it is used and specifications of the programmer.

Можно изменить способ сериализации определенного типа данных, указав один или более признаков сериализациикласса. Как правило, программисту нет необходимости эксплицитно присваивать черты своим классам, поскольку для всех признаков существуют значения по умолчанию. Если значения по умолчанию не подходят, они могут быть назначены программистом. Шаблон используется, чтобы связать имя типа с константой. Например, см.version.hpp.

Version

Этот файл заголовка включает в себя следующий код:<

namespace boost { 
namespace serialization {
template<class T>
struct version
{
    BOOST_STATIC_CONSTANT(unsigned int, value = 0);
};
} // namespace serialization
} // namespace boost
>Для любого класса<T>, Определение по умолчанию<boost::serialization::version<T>::value>равно 0. Если мы хотим назначить значение 2 в качестве версии для класса<my_class>, мы специализируем шаблон версии:<

namespace boost { 
namespace serialization {
struct version<my_class>
{
    BOOST_STATIC_CONSTANT(unsigned int, value = 2);
};
} // namespace serialization
} // namespace boost
>Теперь, когда требуется номер версии для класса<my_class>, значение 2 будет возвращено, а не значение 0 по умолчанию.

Чтобы уменьшить типизацию и повысить читаемость, макро определяется так, чтобы вместо вышеперечисленного мы могли написать:<


BOOST_CLASS_VERSION(my_class, 2)
>, который расширяется до кода выше.

Уровень реализации

Таким же образом, как и выше, указывается «уровень» реализации сериализации. Файл заголовкаlevel.hppопределяет следующее.<

// names for each level
enum level_type
{
    // Don't serialize this type. An attempt to do so should
    // invoke a compile time assertion.
    not_serializable = 0,
    // write/read this type directly to the archive. In this case
    // serialization code won't be called.  This is the default
    // case for fundamental types.  It presumes a member function or
    // template in the archive class that can handle this type.
    // there is no runtime overhead associated reading/writing
    // instances of this level
    primitive_type = 1,
    // 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. 
    object_serializable = 2,
    ///////////////////////////////////////////////////////////////////
    // once an object is serialized at one of the above levels, the
    // corresponding archives cannot be read if the implementation level
    // for the archive object is changed.  
    ///////////////////////////////////////////////////////////////////
    // Add class information to the archive.  Class information includes
    // implementation level, class version and class name if available.
    object_class_info = 3,
};
>Используя макрос, определенный в<level.hpp>, мы можем указать, что<my_class>должно быть сериализовано вместе с номером версии:<

BOOST_CLASS_IMPLEMENTATION(my_class, boost::serialization::object_class_info)
>Если уровень реализации явно не назначен, система использует по умолчанию следующие правила.
  • , если тип данных<volatile>присваивает<not_serializable>
  • , если это числовой или основной тип присваивает<primitive_type>
  • , другой присваивает<object_class_info>
То есть для большинства определяемых пользователем типов объекты будут сериализованы вместе с информацией о версии класса. Это позволит поддерживать обратную совместимость с архивами, которые содержат предыдущие версии. Однако с этой способностью приходит небольшая стоимость выполнения. Для типов, определение которых «никогда» не изменится, эффективность может быть достигнута путем указания<object_serializable>для отмены настройки по умолчанию<object_class_info>. Например, это было сделано для оберткиbinary_object

Object Tracking

В зависимости от способа использования типа может быть необходимо или удобно отслеживать адрес сохраненных и загруженных объектов. Например, это обычно необходимо при сериализации объектов через указатель, чтобы убедиться, что при загрузке архива не создается несколько идентичных объектов. Это «поведение отслеживания» контролируется чертой типа, определенной в файле заголовкаtracking.hpp, которая определяет следующее:<

// names for each tracking level
enum tracking_type
{
    // never track this type
    track_never = 0,
    // track objects of this type if the object is serialized through a 
    // pointer.
    track_selectively = 1,
    // always track this type
    track_always = 2
};
>Соответствующий макрос определен так, что мы можем использовать:<

BOOST_CLASS_TRACKING(my_class, boost::serialization::track_never)
>Характеристики отслеживания по умолчанию:
  • Для примитивных<track_never>
  • . Для указателей<track_never>. То есть адреса адресов по умолчанию не отслеживаются.
  • Все современные обертки для сериализации, такие как<boost::serialization::nvp>,<track_never>.
  • Для всех остальных<track_selectively>. То есть адреса сериализованных объектов отслеживаются тогда и только тогда, когда верно одно или более из следующего:
    • объект этого типа находится где-либо в программе, сериализованной через указатель.
    • класс явно "экспортируется" - см. ниже.
    • класс явно «зарегистрирован» в архиве

Поведение по умолчанию почти всегда самое удобное. Однако есть несколько случаев, когда было бы желательно отменить дефолт. Одним из примеров является виртуальный базовый класс. В структуре наследования алмазов с виртуальным базовым классом отслеживание объектов предотвратит избыточные вызовы сохранения / загрузки. Итак, вот один случай, когда может быть удобно переопределить черту отслеживания по умолчанию.(Примечание: в будущей версии по умолчанию будет реализовано автоматическое отслеживание классов, используемых в качестве виртуальных баз).Эту ситуацию демонстрируетtest_diamond.cpp, включенный в библиотеку.

Экспортный ключ

При сериализации производного класса через виртуальный указатель базового класса могут возникнуть две проблемы.
  • Код в производном классе никогда не может быть явно указан. Такой код никогда не будет реализован.

    Это рассматривается путем вызова<BOOST_CLASS_EXPORT_IMPLEMENT(T)>в файле, который определяет (реализует) класс T. Это гарантирует, что код для производного класса T будет явно инстанцирован.

  • Должен быть какой-то идентификатор, который можно использовать для выбора кода, на который следует ссылаться при загрузке объекта. Стандартный C++ реализует<typeid()>, который может быть использован для возврата уникальной строки для класса. Это не совсем удовлетворительно для наших целей по следующим причинам:
    • Нет никакой гарантии, что строка одинакова на разных платформах. В этом случае не будет поддержки переносных архивов.
    • При использовании модулей кода из различных источников классы могут быть обернуты в разные пространства имен в разных программах.
    • В разных модулях кода, имеющих одно и то же имя, могут быть классы, определяемые локально.
    • Для целей сериализации могут существовать классы с разными названиями, которые мы хотим считать эквивалентными.

    Таким образом, в библиотеке сериализации это рассматривается путем вызова<BOOST_CLASS_EXPORT_KEY2(my_class, "my_class_external_identifier")>в файле заголовка, который объявляет класс. В большинстве приложений имя класса отлично подходит для строки внешнего идентификатора, поэтому определяется следующий короткий отрезок -<BOOST_CLASS_EXPORT_KEY(my_class)>

. Для программ, которые состоят только из одного модуля, то есть программ, которые не используют DLLS, можно указать<BOOST_CLASS_EXPORT(my_class)>или<BOOST_CLASS_EXPORT_GUID(my_class, "my_class_external_identifier")>в заголовке декларации или определении. Эти макросы расширяются до вызова обоих описанных выше макросов.[GUIDозначаетGлобальныйUникеIDentfier.]

В другом местев этом руководстве подробно рассматривается сериализация производных классов.

Файл заголовкаexport.hppсодержит все макроопределения, описанные здесь. В библиотеке будет сделано исключение, если

  • Тип, не упомянутый явно, не экспортируется.
  • Код сериализации для одного и того же типа инстанцируется более чем в одном модуле (или DLL).

Аннотация

При сериализации объекта через указатель на его базовый класс библиотеке необходимо определить, является ли база абстрактной (т.е. имеет по меньшей мере одну виртуальную функцию). Для этого библиотека использует макрос черт типа<BOOST_IS_ABSTRACT(T)>. Не все компиляторы поддерживают этот тип и соответствующий макрос. Для решения этой проблемы был реализован макрос< BOOST_SERIALIZATION_ASSUME_ABSTRACT(T)>, позволяющий явно указать, что определенный тип на самом деле является абстрактным. Это гарантирует, что<BOOST_IS_ABSTRACT>вернет правильное значение для всех компиляторов.

Реализация типовой информации

Эта последняя черта также связана с сериализацией объектов через указатель базового класса. Реализация этого объекта требует способности определять во время выполнения истинный тип объекта, на который указывает указатель базового класса. Различные системы сериализации делают это по-разному. В нашей системе по умолчанию используется функция<typeid(...)>, которая доступна в системах, поддерживающихRTTIRunTimeTypeInformation. Это будет удовлетворительно почти во всех случаях, и большинство пользователей этой библиотеки ничего не потеряют, пропустив этот раздел руководства.

Однако в некоторых случаях система определения типа по умолчанию не удобна. Некоторые платформы могут не поддерживать RTTI или быть отключены для ускорения выполнения или по какой-либо другой причине. Некоторые приложения, например E.G. runtime linking of plug-in modules, не могут зависеть от C++ RTTI для определения истинного производного класса. RTTI возвращает только правильный тип для полиморфных классов — классов с хотя бы одной виртуальной функцией. Если какая-либо из этих ситуаций применима, можно заменить свою собственную реализацию<extended_type_info>.

Интерфейс средств, необходимых для реализации сериализации, определен вextended_type_info.hpp. По умолчанию реализация этих средств на основе<typeid(...)>определена вextended_type_info_typeid.hpp. Альтернативная реализация, основанная на экспортируемых идентификаторах классов, определена вextended_type_info_no_rtti.hpp.

Применив макрос:<


BOOST_CLASS_TYPE_INFO(
    my_class, 
    extended_type_info_no_rtti<my_class>
)
>мы можем назначить реализацию информации о типе каждому классу на индивидуальной основе. Не требуется, чтобы все классы в программе использовали одну и ту же реализацию<extended_type_info>. Это поддерживает концепцию, что сериализация каждого класса указывается «раз и навсегда» в файле заголовка, который может быть включен в любой проект без изменений.

Это иллюстрируется тестовой программойtest_no_rtti.cpp. Возможны и могут потребоваться другие варианты осуществления в определенных особых случаях.

Обертки

Архивы должны относиться к оберткам иначе, чем к другим типам, поскольку, например, они обычно представляют собой неконстовые объекты, в то время как выходные архивы требуют, чтобы любой сериализованный объект (за исключением обертки) был конст. Этот файл заголовкаwrapper.hppсодержит следующий код:<

namespace boost { 
namespace serialization {
template<class T>
struct is_wrapper
 : public mpl::false_
{};
} // namespace serialization
} // namespace boost
>Для любого класса<T>, Таким образом, определение по умолчанию<boost::serialization::is_wrapper<T>::value>является ложным. Если мы хотим заявить, что класс<my_class>является оберткой, мы специализируемся на шаблоне версии:<

namespace boost { 
namespace serialization {
struct is_wrapper<my_class>
 : mpl::true_
{};
} // namespace serialization
} // namespace boost
>

Чтобы уменьшить типизацию и улучшить читаемость, макрос определяется таким образом, что вместо вышеперечисленного мы можем написать:<


BOOST_CLASS_IS_WRAPPER(my_class)
>, который расширяется до кода выше.

Битуазная сериализация

Некоторые простые классы могут быть сериализованы путем прямого копирования всех битов класса. Это, в частности, относится к типам данных POD, которые не содержат указателей, и которые не являются ни версиями, ни отслеживаемыми. Некоторые архивы, такие как непортативные двоичные архивы, могут сделать нас из этой информации, чтобы значительно ускорить сериализацию. Для указания возможности побитовой сериализации используется признак типа, определенный в файле заголовкаis_bitwise_serializable.hpp:<

namespace boost { namespace serialization {
    template
    struct is_bitwise_serializable
     : public is_arithmetic
    {};
} }
>, и может быть специализирован для других классов. Специализация упрощается соответствующим макросом:<

BOOST_IS_BITWISE_SERIALIZABLE(my_class)
>

Черты сериализации шаблонов

В некоторых случаях может быть удобно назначить черты сериализации сразу целой группе классов. Рассмотрим обертку пары имени-значения<

template<class T>
struct nvp : public std::pair<const char *, T *>
{
    ...
};
>, используемую архивами XML для связи имени с переменной данных типа T. Эти типы данных никогда не отслеживаются и никогда не редактируются. Таким образом, можно захотеть указать:<

BOOST_CLASS_IMPLEMENTATION(nvp<T>, boost::serialization::level_type::object_serializable)
BOOST_CLASS_TRACKING(nvp<T>, boost::serialization::track_never)
>Изучение определения этих макросов показывает, что они не будут расширяться до разумного кода при использовании с аргументом шаблона. Таким образом, вместо использования удобных макросов, используйте оригинальные определения<

template<class T>
struct implementation_level<nvp<T> >
{
    typedef mpl::integral_c_tag tag;
    typedef mpl::int_<object_serializable> type;
    BOOST_STATIC_CONSTANT(
        int,
        value = implementation_level::type::value
    );
};
// nvp objects are generally created on the stack and are never tracked
template<class T>
struct tracking_level<nvp<T> >
{
    typedef mpl::integral_c_tag tag;
    typedef mpl::int_<track_never> type;
    BOOST_STATIC_CONSTANT(
        int, 
        value = tracking_level::type::value
    );
};
>, чтобы присвоить черты сериализации всем классам, генерируемым шаблоном<nvp<T>>.

Обратите внимание, что при использовании компиляторов, которые правильно поддерживают Partial Template Specialization, можно использовать только указанный выше метод для присвоения черт шаблонам. Первое, что нужно сделать, это сделать что-то вроде:<


#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
template<class T>
struct implementation_level<nvp<T> >
{
   ... // see above
};
// nvp objects are generally created on the stack and are never tracked
template<class T>
struct tracking_level<nvp<T> >
{
   ... // see above
};
#endif
>Это может быть проблематично, когда кто-то хочет сделать свой коди архивыпереносимыми на другие платформы. Это означает, что объекты будут сериализоваться по-разному в зависимости от используемой платформы. Это означает, что объекты, сохраненные с одной платформы, не будут загружаться должным образом на другую. Другими словами, архивы не будут портативными.

Эта проблема решается путем создания другого метода присвоения пользовательским классам признаков сериализации. Это иллюстрируется сериализацией для парыимени-значения.

В частности, это влечет за собой извлечение шаблона из специального класса.<boost::serialization::traits>, который специализируется на конкретной комбинации признаков сериализации. При поиске признаков сериализации библиотека сначала проверяет, использовался ли этот класс в качестве базового. Если да, то используются соответствующие признаки. В противном случае используются стандартные дефолты. Происходя из класса признаков сериализации, а не полагаясь на Partial Template Specializaton, можно применить черты сериализации к шаблону, и эти черты будут одинаковыми на всех известных платформах.

Подпись для шаблона признаков:<


template<
    class T,       
    int Level, 
    int Tracking,
    unsigned int Version = 0,
    class ETII = BOOST_SERIALIZATION_DEFAULT_TYPE_INFO(T),
    class IsWrapper = mpl::false_
>
struct traits
>и параметры шаблона должны быть назначены согласно следующей таблице:

описаниеописаниедопустимые значениязначение по умолчанию
целевого классаназвание классауровень реализацииуровеньуровень отслеживанияПредупреждения и ошибкиНекоторые черты сериализации могут конфликтовать с другими. Иногда эти конфликты приводят к ошибочному поведению (создание архивов, которые не могут быть прочитаны), а иногда они представляют собой вероятное заблуждение со стороны пользователя библиотеки, которое может привести к неожиданному поведению. По мере возможности эти конфликты обнаруживаются во время компиляции и генерируются ошибки (BOOST_STATIC_ASSERT) или предупреждения (BOOST_STATIC_WARNING). Они генерируются зависимым от компилятора способом, который должен показывать цепочку инстанциации до точки, где обнаружена ошибка / предупреждение. Без этой возможности было бы очень трудно отследить ошибки или неожиданное поведение при использовании библиотеки. Вот список захваченных конфликтов:

объект_уровень— ошибка

Эта ошибка ловушка пытается сериализовать типы, уровень импленсации которых установлен на несериализируемый.

объект_версия- ошибка

Возможно, по соображениям эффективности типу может быть присвоен уровень сериализации, который не включает информацию о типе в архив. Это исключило бы присвоение типу нового номера версии. Эта ошибка ловушки попытки назначить номер версии в этом случае. Это должно быть ошибкой пользователя.

Object_tracking- предупреждение

При компиляции следующего кода будет отображаться сообщение:<
T t;
ar << t;
>, если черта сериализации уровня отслеживания не установлена на «track_never». Ниже без проблем будут собраны:<
const T t
ar << t;
>Аналогично, следующий код будет ловить во время компиляции:<
T * t;
ar >>t;
>, если черта сериализации уровня отслеживания установлена на «track_never».

Следующий случай иллюстрирует функцию этого сообщения. Первоначально он использовался в качестве примера в списке рассылки Петром Димовым.<

class construct_from 
{ 
    ... 
}; 
void main(){ 
    ... 
    Y y; 
    construct_from x(y); 
    ar << x; 
} 
>Допустим, что вышеупомянутое сообщение не отображается и код используется как есть.
  1. Этот пример прекрасно компилирует и исполняет. Отслеживание не производится, потому что build_from никогда не был сериализован через указатель. Спустя некоторое время появляется следующий программист(2) и делает усовершенствование. Он хочет, чтобы архив был чем-то вроде журнала.<
    void main(){ 
        ... 
        Y y; 
        construct_from x(y); 
        ar << x; 
        ... 
        x.f(); // change x in some way 
       ... 
        ar << x 
    } 
    
    >

    Опять никаких проблем. Он получает в архиве две разные копии, каждая из которых отличается. То есть он получает именно то, что ожидает и естественно радуется.

  2. Спустя некоторое время третий программист(3) видит конструктор_из и говорит - о, круто, именно то, что мне нужно. Он пишет функцию в полностью несвязном модуле. (Проект настолько большой, что он даже не осознает существования оригинального использования) и пишет что-то вроде:<
    class K { 
        shared_ptr <construct_from> z; 
        template <class Archive> 
        void serialize(Archive & ar, const unsigned version){ 
            ar << z; 
        } 
    }; 
    
    >

    Он строит и запускает программу и тестирует свою новую функциональность. Он отлично работает, и он в восторге.

  3. Все идет гладко, как и прежде. Проходит месяц, и обнаруживается, что при загрузке архивов, сделанных в последний месяц (чтение журнала). Все не работает. Вторая запись журнала всегда такая же, как и первая. После серии очень длинных и все более акримониальных обменов электронной почтой выяснилось, что программист (3) случайно нарушил код программиста (2). Это связано с тем, что путем сериализации с помощью указателя объект «log» теперь отслеживается. Это связано с тем, что поведение отслеживания по умолчанию является «track_selectively». Это означает, что классные экземпляры отслеживаются только в том случае, если они сериализованы через указатели в любом месте программы. Теперь несколько сохранений с одного и того же адреса приводят к тому, что в архив записывается только первый. Последующие сохранения добавляют только адрес, даже если данные могли быть изменены. Когда приходит время загрузки данных, все экземпляры записи журнала показывают одни и те же данные. Таким образом, поведение функционирующего фрагмента кода изменяется из-за побочного эффекта изменения в несвязанном модуле. Хуже того, данные были потеряны и не могут быть восстановлены из архивов. Люди действительно расстроены и разочарованы повышением (по крайней мере, система сериализации).

  4. После долгих исследований было обнаружено, что является источником проблемы, и конструкция класса из отмечена «track_never», включив:<
    BOOST_CLASS_TRACKING(construct_from, track_never) 
    
    >
  5. Теперь все работает снова. Или - так кажется.

  6. <shared_ptr<construct_from>>не будет иметь ни одного необработанного указателя между экземплярами. Каждый из них<shared_ptr<construct_from>>будет иметь свой собственный четкий указатель. Это сломает<shared_ptr>и вызовет утечку памяти. Опять же, Причина этой проблемы очень далека от точки открытия. Вполне возможно, что проблема не будет обнаружена даже после загрузки архивов. Теперь нам не только трудно найти и исправить ошибку программы, но у нас есть куча недействительных архивов и потерянных данных.

Теперь рассмотрим, что происходит, когда сообщение отображается:

  1. Прямо сейчас программа ловит<
    ar << x; 
    
    >

  2. Программист проклинает (еще один %) прыжок. Он спешит (а кто нет) и предпочёл бы не<const_cast>— потому что выглядит плохо. Так что он просто сделает следующее изменение.<
    Y y; 
    const construct_from x(y); 
    ar << x; 
    
    >

    Все работает хорошо, и он движется дальше.

  3. Теперь программист (2) хочет внести свою перемену - и снова еще одна раздражающая проблема;<
    Y y; 
    const construct_from x(y); 
    ... 
    x.f(); // change x in some way ; compile error f() is not const 
    ... 
    ar << x 
    
    >

    Он слегка раздражен, теперь он пробует следующее:

    • Он считает, что делает f() const - но предположительно, что сдвигает ошибку const в другое место. И он не хочет возиться со своим кодом, чтобы обойти причуду в системе сериализации

    • .<const>из<const construct_from>выше — теперь он получает ловушку. Если он посмотрит на код комментария, где происходит<BOOST_STATIC_ASSERT>, он сделает одну из двух вещей

      1. . Это просто безумие. Это делает мою жизнь неоправданно сложной и помечает код, который просто отлично. Так что я исправлю это<const_cast>и подам жалобу в список, и они исправят это. В этом случае история переходит на предыдущий сценарий.

      2. О, эта ловушка предполагает, что сериализация по умолчанию на самом деле не то, что я хочу. Конечно, в этой конкретной программе это не имеет значения. Но тогда код в ловушке не может реально оценить код в других модулях (которые могут даже не быть написаны еще). Хорошо, я добавлю следующее в мой конструктор_from.hpp, чтобы решить проблему.<
        BOOST_CLASS_TRACKING(construct_from, track_never) 
        
        >

  4. Теперь приходит программист (3) и делает свое изменение. Поведение оригинала (и удаленного модуля) остается неизменным, потому что<construct_from>признак был установлен на «track_never», поэтому он всегда должен получать копии, и журнал должен быть тем, что мы ожидаем.

  5. Но теперь он попадает в другую ловушку — пытается спасти объект класса с пометкой «track_never» через указатель. Поэтому он возвращается к construct_from.hpp и комментирует<BOOST_CLASS_TRACKING>, который был вставлен. Теперь второй ловушки избегают, Но черт - первая ловушка снова всплывает. В конце концов, после некоторой реструктуризации кода различные требования сериализации<construct_from>примиряются.
Обратите внимание, что в этом втором сценарии
  • все ошибки попадают в ловушку во время компиляции.
  • Недействительные архивы не создаются.
  • Данные не теряются.
  • Погрешности не возникают.
Это правда, что эти сообщения могут иногда помечать код, который в настоящее время является правильным, и что это может раздражать некоторых программистов. Однако этот пример иллюстрирует мое мнение о том, что эти сообщения полезны и что любое такое раздражение - это небольшая цена, которую нужно заплатить, чтобы избежать особенно досадных ошибок программирования.

pointer_level- предупреждение

Эта ловушка обращается к следующему пункту при сериализации указателя:
  • Тип не сохраняет информацию о классе в архиве. То есть уровень реализации признаков сериализации<= object_serializable.
  • Отслеживание для этого типа настроено на «отслеживание выборочно» в этом случае указание на то, что отслеживаемый объект не хранится в самом архиве — см. уровень == object_serializable. Поскольку информация о классе не сохраняется в архиве, для вывода о том, что объект этого типа должен отслеживаться, используется наличие или отсутствие операции ar<< T * в любом другом месте программы.

    Проблема возникает, когда программа, которая читает архив, включает операцию T * для того, чтобы информация отслеживания была включена в архив. Когда программа, которая создает архив, не включает ar<< T, предполагается, что архив не содержит информацию отслеживания, и архив не будет загружаться. Обратная ситуация также может вызвать аналогичную проблему.

    Хотя такая ситуация маловероятна по нескольким причинам, она возможна — отсюда и это предупреждение.

Поэтому, если ваша программа попадает в ловушку, подумайте об изменении признаков уровня отслеживания или реализации или не сериализации с помощью указателя.

pointer_tracking— предупреждение

Сериализация объекта с пометкой «track_never» через указатель может привести к созданию большего количества объектов, чем было сохранено. Есть случаи, когда пользователь может действительно захотеть сделать это, поэтому мы оставляем это в качестве предупреждения.

const_loading- ошибка

Нельзя загружать данные в объект «const», если это не обертка вокруг какого-либо другого объекта, не являющегося объектом «const».

© CopyrightRobert Ramey2002-2004 и Matthias Troyer 2006. Распространяется под лицензией Boost Software License, версия 1.0. (См. сопроводительный файл LICENSE_1_0.txt или копию по адресу http://www.boost.org/LICENSE_1_0.txt)

Статья Serialization - Class Serialization Traits раздела может быть полезна для разработчиков на c++ и boost.




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.



:: Главная :: ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-08-30 11:47:00
2025-07-05 10:41:33/0.015733003616333/0