LCOV - code coverage report
Current view: top level - cereal - cereal.hpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 8775 8775 100.0 %
Date: 2019-10-22 20:09:23 Functions: 12065 12300 98.1 %

          Line data    Source code
       1             : /*! \file cereal.hpp
       2             :     \brief Main cereal functionality */
       3             : /*
       4             :   Copyright (c) 2014, Randolph Voorhies, Shane Grant
       5             :   All rights reserved.
       6             : 
       7             :   Redistribution and use in source and binary forms, with or without
       8             :   modification, are permitted provided that the following conditions are met:
       9             :       * Redistributions of source code must retain the above copyright
      10             :         notice, this list of conditions and the following disclaimer.
      11             :       * Redistributions in binary form must reproduce the above copyright
      12             :         notice, this list of conditions and the following disclaimer in the
      13             :         documentation and/or other materials provided with the distribution.
      14             :       * Neither the name of cereal nor the
      15             :         names of its contributors may be used to endorse or promote products
      16             :         derived from this software without specific prior written permission.
      17             : 
      18             :   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
      19             :   ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
      20             :   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
      21             :   DISCLAIMED. IN NO EVENT SHALL RANDOLPH VOORHIES OR SHANE GRANT BE LIABLE FOR ANY
      22             :   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
      23             :   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
      24             :   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
      25             :   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      26             :   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
      27             :   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      28             : */
      29             : #ifndef CEREAL_CEREAL_HPP_
      30             : #define CEREAL_CEREAL_HPP_
      31             : 
      32             : #include <type_traits>
      33             : #include <string>
      34             : #include <memory>
      35             : #include <functional>
      36             : #include <unordered_map>
      37             : #include <unordered_set>
      38             : #include <vector>
      39             : #include <cstddef>
      40             : #include <cstdint>
      41             : #include <functional>
      42             : 
      43             : #include "cereal/macros.hpp"
      44             : #include "cereal/details/traits.hpp"
      45             : #include "cereal/details/helpers.hpp"
      46             : #include "cereal/types/base_class.hpp"
      47             : 
      48             : namespace cereal
      49             : {
      50             :   // ######################################################################
      51             :   //! Creates a name value pair
      52             :   /*! @relates NameValuePair
      53             :       @ingroup Utility */
      54             :   template <class T> inline
      55        5200 :   NameValuePair<T> make_nvp( std::string const & name, T && value )
      56             :   {
      57        5200 :     return {name.c_str(), std::forward<T>(value)};
      58             :   }
      59         800 : 
      60             :   //! Creates a name value pair
      61         800 :   /*! @relates NameValuePair
      62             :       @ingroup Utility */
      63         800 :   template <class T> inline
      64             :   NameValuePair<T> make_nvp( const char * name, T && value )
      65         800 :   {
      66             :     return {name, std::forward<T>(value)};
      67         800 :   }
      68             : 
      69         800 :   //! Creates a name value pair for the variable T with the same name as the variable
      70             :   /*! @relates NameValuePair
      71        2800 :       @ingroup Utility */
      72             :   #define CEREAL_NVP(T) ::cereal::make_nvp(#T, T)
      73        2800 : 
      74             :   // ######################################################################
      75             :   //! Convenience function to create binary data for both const and non const pointers
      76             :   /*! @param data Pointer to beginning of the data
      77             :       @param size The size in bytes of the data
      78             :       @relates BinaryData
      79             :       @ingroup Utility */
      80        2800 :   template <class T> inline
      81      574906 :   BinaryData<T> binary_data( T && data, size_t size )
      82        2800 :   {
      83      574906 :     return {std::forward<T>(data), size};
      84        1600 :   }
      85      285453 : 
      86        1600 :   // ######################################################################
      87      285453 :   //! Creates a size tag from some variable.
      88        1200 :   /*! Will normally be used to serialize size (e.g. size()) information for
      89      285453 :       variable size containers.  If you have a variable sized container,
      90        1200 :       the very first thing it serializes should be its size, wrapped in
      91      285453 :       a SizeTag.
      92             : 
      93         400 :       @relates SizeTag
      94             :       @ingroup Utility */
      95         400 :   template <class T> inline
      96       72000 :   SizeTag<T> make_size_tag( T && sz )
      97         400 :   {
      98       72000 :     return {std::forward<T>(sz)};
      99         400 :   }
     100       36000 : 
     101         400 :   // ######################################################################
     102       36000 :   //! Marks data for deferred serialization
     103         400 :   /*! cereal performs a recursive depth-first traversal of data it serializes. When
     104      694106 :       serializing smart pointers to large, nested, or cyclical data structures, it
     105         400 :       is possible to encounter a stack overflow from excessive recursion when following
     106      694106 :       a chain of pointers.
     107         400 : 
     108      329053 :       Deferment can help in these situations if the data can be serialized separately from
     109         400 :       the pointers used to traverse the structure. For example, a graph structure can have its
     110      329053 :       nodes serialized before its edges:
     111         400 : 
     112      329053 :       @code{.cpp}
     113         400 :       struct MyEdge
     114      329053 :       {
     115         400 :         std::shared_ptr<MyNode> connection;
     116             :         int some_value;
     117             : 
     118             :         template<class Archive>
     119      232254 :         void serialize(Archive & archive)
     120      233054 :         {
     121        2301 :           // when we serialize an edge, we'll defer serializing the associated node
     122       11101 :           archive( cereal::defer( connection ),
     123        2700 :                    some_value );
     124       11100 :         }
     125       14100 :       };
     126       16100 : 
     127     6268600 :       struct MyGraphStructure
     128     6273800 :       {
     129        3400 :         std::vector<MyEdge> edges;
     130        8600 :         std::vector<MyNodes> nodes;
     131      812300 : 
     132      815500 :         template<class Archive>
     133        5700 :         void serialize(Archive & archive)
     134        8900 :         {
     135    10896764 :           // because of the deferment, we ensure all nodes are fully serialized
     136    10899964 :           // before any connection pointers to those nodes are serialized
     137       64414 :           archive( edges, nodes );
     138       67614 : 
     139       82537 :           // we have to explicitly inform the archive when it is safe to serialize
     140       84137 :           // the deferred data
     141       84004 :           archive.serializeDeferments();
     142       85604 :         }
     143       65313 :       };
     144       66913 :       @endcode
     145       69305 : 
     146       69305 :       @relates DeferredData
     147       54299 :       @ingroup Utility */
     148       54299 :   template <class T> inline
     149       65604 :   DeferredData<T> defer( T && value )
     150       65604 :   {
     151       60937 :     return {std::forward<T>(value)};
     152       60937 :   }
     153       65204 : 
     154       65204 :   // ######################################################################
     155      589079 :   //! Called before a type is serialized to set up any special archive state
     156      589079 :   //! for processing some type
     157       65608 :   /*! If designing a serializer that needs to set up any kind of special
     158       65608 :       state or output extra information for a type, specialize this function
     159       70105 :       for the archive type and the types that require the extra information.
     160       70105 :       @ingroup Internal */
     161       79442 :   template <class Archive, class T> inline
     162      311696 :   void prologue( Archive & /* archive */, T const & /* data */)
     163      320413 :   { }
     164       90460 : 
     165       93418 :   //! Called after a type is serialized to tear down any special archive state
     166       85817 :   //! for processing some type
     167       75608 :   /*! @ingroup Internal */
     168       79008 :   template <class Archive, class T> inline
     169      103739 :   void epilogue( Archive & /* archive */, T const & /* data */)
     170     6369639 :   { }
     171     6347599 : 
     172       68499 :   // ######################################################################
     173       77803 :   //! Special flags for archives
     174      884603 :   /*! AllowEmptyClassElision
     175      880722 :         This allows for empty classes to be serialized even if they do not provide
     176       72522 :         a serialization function.  Classes with no data members are considered to be
     177      154403 :         empty.  Be warned that if this is enabled and you attempt to serialize an
     178    11047919 :         empty class with improperly formed serialize or load/save functions, no
     179    11140320 :         static error will occur - the error will propogate silently and your
     180      302516 :         intended serialization functions may not be called.  You can manually
     181      233250 :         ensure that your classes that have custom serialization are correct
     182      250367 :         by using the traits is_output_serializable and is_input_serializable
     183      185402 :         in cereal/details/traits.hpp.
     184      184977 :       @ingroup Internal */
     185      336442 :   enum Flags { AllowEmptyClassElision = 1 };
     186      315748 : 
     187      407752 :   // ######################################################################
     188      410654 :   //! Registers a specific Archive type with cereal
     189      561554 :   /*! This registration should be done once per archive.  A good place to
     190      551139 :       put this is immediately following the definition of your archive.
     191      195100 :       Archive registration is only strictly necessary if you wish to
     192      201507 :       support pointers to polymorphic data types.  All archives that
     193      250209 :       come with cereal are already registered.
     194      246758 :       @ingroup Internal */
     195      998857 :   #define CEREAL_REGISTER_ARCHIVE(Archive)                              \
     196     1014708 :   namespace cereal { namespace detail {                                 \
     197      209508 :   template <class T, class BindingTag>                                  \
     198      714588 :   typename polymorphic_serialization_support<Archive, T>::type          \
     199      776163 :   instantiate_polymorphic_binding( T*, Archive*, BindingTag, adl_tag ); \
     200      259587 :   } } /* end namespaces */
     201      264810 : 
     202      278326 :   //! Helper macro to omit unused warning
     203      273827 :   #if defined(__GNUC__)
     204      273577 :     // GCC / clang don't want the function
     205      191177 :     #define CEREAL_UNUSED_FUNCTION
     206      199637 :   #else
     207      943975 :     #define CEREAL_UNUSED_FUNCTION static void unused() { (void)version; }
     208      938803 :   #endif
     209      140368 : 
     210      123317 :   // ######################################################################
     211      179312 :   //! Defines a class version for some type
     212      256372 :   /*! Versioning information is optional and adds some small amount of
     213      280172 :       overhead to serialization.  This overhead will occur both in terms of
     214      203101 :       space in the archive (the version information for each class will be
     215      209001 :       stored exactly once) as well as runtime (versioned serialization functions
     216      216132 :       must check to see if they need to load or store version information).
     217      196132 : 
     218      235475 :       Versioning is useful if you plan on fundamentally changing the way some
     219     1036866 :       type is serialized in the future.  Versioned serialization functions
     220     1071898 :       cannot be used to load non-versioned data.
     221      209776 : 
     222      300377 :       By default, all types have an assumed version value of zero.  By
     223      361877 :       using this macro, you may change the version number associated with
     224      290444 :       some type.  cereal will then use this value as a second parameter
     225      460144 :       to your serialization functions.
     226      877255 : 
     227      707155 :       The interface for the serialization functions is nearly identical
     228      373341 :       to non-versioned serialization with the addition of a second parameter,
     229      274106 :       const std::uint32_t version, which will be supplied with the correct
     230      389359 :       version number.  Serializing the version number on a save happens
     231      488959 :       automatically.
     232      616600 : 
     233      540867 :       Versioning cannot be mixed with non-versioned serialization functions.
     234     4907808 :       Having both types will result result in a compile time error.  Data
     235     4915142 :       serialized without versioning cannot be loaded by a serialization
     236      241049 :       function with added versioning support.
     237      429585 : 
     238     1992678 :       Example interface for versioning on a non-member serialize function:
     239     1844676 : 
     240      231582 :       @code{cpp}
     241      219275 :       CEREAL_CLASS_VERSION( Mytype, 77 ); // register class version
     242      277761 : 
     243      297265 :       template <class Archive>
     244      307276 :       void serialize( Archive & ar, Mytype & t, const std::uint32_t version )
     245      308045 :       {
     246      306345 :         // When performing a load, the version associated with the class
     247      277241 :         // is whatever it was when that data was originally serialized
     248      187341 :         //
     249      367252 :         // When we save, we'll use the version that is defined in the macro
     250     1604021 : 
     251     1433321 :         if( version >= some_number )
     252      142851 :           // do this
     253      121897 :         else
     254      199493 :           // do that
     255      244924 :       }
     256      255824 :       @endcode
     257      402305 : 
     258      398505 :       Interfaces for other forms of serialization functions is similar.  This
     259      436867 :       macro should be placed at global scope.
     260      417667 :       @ingroup Utility */
     261      243908 :   #define CEREAL_CLASS_VERSION(TYPE, VERSION_NUMBER)                             \
     262     1134904 :   namespace cereal { namespace detail {                                          \
     263     1175028 :     template <> struct Version<TYPE>                                             \
     264      220408 :     {                                                                            \
     265      193276 :       static const std::uint32_t version;                                        \
     266      786575 :       static std::uint32_t registerVersion()                                     \
     267      718079 :       {                                                                          \
     268      358779 :         ::cereal::detail::StaticObject<Versions>::getInstance().mapping.emplace( \
     269     1000877 :              std::type_index(typeid(TYPE)).hash_code(), VERSION_NUMBER );        \
     270      840277 :         return VERSION_NUMBER;                                                   \
     271      208362 :       }                                                                          \
     272      112451 :       CEREAL_UNUSED_FUNCTION                                                     \
     273      146769 :     }; /* end Version */                                                         \
     274      242289 :     const std::uint32_t Version<TYPE>::version =                                 \
     275      406409 :       Version<TYPE>::registerVersion();                                          \
     276      397333 :   } } // end namespaces
     277     4920133 : 
     278     4931092 :   // ######################################################################
     279      199978 :   //! The base output archive class
     280      402089 :   /*! This is the base output archive for all output archives.  If you create
     281     1287793 :       a custom archive class, it should derive from this, passing itself as
     282     1044298 :       a template parameter for the ArchiveType.
     283      171693 : 
     284      171991 :       The base class provides all of the functionality necessary to
     285      170923 :       properly forward data to the correct serialization functions.
     286      278808 : 
     287      433504 :       Individual archives should use a combination of prologue and
     288      338507 :       epilogue functions together with specializations of serialize, save,
     289      178047 :       and load to alter the functionality of their serialization.
     290      147741 : 
     291      150841 :       @tparam ArchiveType The archive type that derives from OutputArchive
     292      341949 :       @tparam Flags Flags to control advanced functionality.  See the Flags
     293     1033831 :                     enum for more information.
     294     2018032 :       @ingroup Internal */
     295     1325330 :   template<class ArchiveType, std::uint32_t Flags = 0>
     296      236501 :   class OutputArchive : public detail::OutputArchiveBase
     297      258522 :   {
     298      336693 :     public:
     299      405425 :       //! Construct the output archive
     300      517010 :       /*! @param derived A pointer to the derived ArchiveType (pass this from the derived archive) */
     301      507438 :       OutputArchive(ArchiveType * const derived) : self(derived), itsCurrentPointerId(1), itsCurrentPolymorphicTypeId(1)
     302     1272537 :       { }
     303     1189142 : 
     304      170942 :       OutputArchive & operator=( OutputArchive const & ) = delete;
     305      260440 : 
     306      433848 :       //! Serializes all passed in data
     307      423017 :       /*! This is the primary interface for serializing data with an archive */
     308      465401 :       template <class ... Types> inline
     309     1111632 :       ArchiveType & operator()( Types && ... args )
     310     1033038 :       {
     311      296005 :         self->process( std::forward<Types>( args )... );
     312      378803 :         return *self;
     313      466038 :       }
     314     1043341 : 
     315      991089 :       //! Serializes any data marked for deferment
     316      195290 :       /*! This will cause any data wrapped in DeferredData to be immediately serialized
     317      332015 :           @relates defer */
     318      615677 :       void serializeDeferments()
     319      626369 :       {
     320      406070 :         for( auto & deferment : itsDeferments )
     321      642969 :           deferment();
     322      644907 :       }
     323      320206 : 
     324      394903 :       /*! @name Boost Transition Layer
     325      350843 :           Functionality that mirrors the syntax for Boost.  This is useful if you are transitioning
     326     1005540 :           a large project from Boost to cereal.  The preferred interface for cereal is using operator(). */
     327      974107 :       //! @{
     328      168477 : 
     329      258470 :       //! Indicates this archive is not intended for loading
     330      495364 :       /*! This ensures compatibility with boost archive types.  If you are transitioning
     331      411067 :           from boost, you can check this value within a member or external serialize function
     332      320686 :           (i.e., Archive::is_loading::value) to disable behavior specific to loading, until
     333      331713 :           you can transition to split save/load or save_minimal/load_minimal functions */
     334      420413 :       using is_loading = std::false_type;
     335      412149 : 
     336      449397 :       //! Indicates this archive is intended for saving
     337     1772127 :       /*! This ensures compatibility with boost archive types.  If you are transitioning
     338     1492226 :           from boost, you can check this value within a member or external serialize function
     339      590836 :           (i.e., Archive::is_saving::value) to enable behavior specific to loading, until
     340      593186 :           you can transition to split save/load or save_minimal/load_minimal functions */
     341      324333 :       using is_saving = std::true_type;
     342      382758 : 
     343      291524 :       //! Serializes passed in data
     344      302876 :       /*! This is a boost compatability layer and is not the preferred way of using
     345     1028644 :           cereal.  If you are transitioning from boost, use this until you can
     346     3451256 :           transition to the operator() overload */
     347     2663337 :       template <class T> inline
     348      196337 :       ArchiveType & operator&( T && arg )
     349      265068 :       {
     350      357804 :         self->process( std::forward<T>( arg ) );
     351      436898 :         return *self;
     352      541446 :       }
     353      511452 : 
     354      293027 :       //! Serializes passed in data
     355      216628 :       /*! This is a boost compatability layer and is not the preferred way of using
     356      285422 :           cereal.  If you are transitioning from boost, use this until you can
     357     1011621 :           transition to the operator() overload */
     358     2168860 :       template <class T> inline
     359     1362560 :       ArchiveType & operator<<( T && arg )
     360      308000 :       {
     361      384900 :         self->process( std::forward<T>( arg ) );
     362      839793 :         return *self;
     363      800594 :       }
     364      545653 : 
     365      563551 :       //! @}
     366     2700802 : 
     367     2701904 :       //! Registers a shared pointer with the archive
     368      285154 :       /*! This function is used to track shared pointer targets to prevent
     369     1005154 :           unnecessary saves from taking place if multiple shared pointers
     370     1456557 :           point to the same data.
     371      648657 : 
     372      157162 :           @internal
     373      244261 :           @param addr The address (see shared_ptr get()) pointed to by the shared pointer
     374      243236 :           @return A key that uniquely identifies the pointer */
     375      315337 :       inline std::uint32_t registerSharedPointer( void const * addr )
     376      367493 :       {
     377      446893 :         // Handle null pointers by just returning 0
     378      400578 :         if(addr == 0) return 0;
     379      236977 : 
     380      407395 :         auto id = itsSharedPointerMap.find( addr );
     381      326994 :         if( id == itsSharedPointerMap.end() )
     382      492346 :         {
     383      490622 :           auto ptrId = itsCurrentPointerId++;
     384      123078 :           itsSharedPointerMap.insert( {addr, ptrId} );
     385      112802 :           return ptrId | detail::msb_32bit; // mask MSB to be 1
     386      110885 :         }
     387      111986 :         else
     388      133181 :           return id->second;
     389     2642581 :       }
     390     2652755 : 
     391      185955 :       //! Registers a polymorphic type name with the archive
     392      337434 :       /*! This function is used to track polymorphic types to prevent
     393      347733 :           unnecessary saves of identifying strings used by the polymorphic
     394      187290 :           support functionality.
     395      174890 : 
     396      134302 :           @internal
     397      164602 :           @param name The name to associate with a polymorphic type
     398      183121 :           @return A key that uniquely identifies the polymorphic type name */
     399      135321 :       inline std::uint32_t registerPolymorphicType( char const * name )
     400      116502 :       {
     401     1320149 :         auto id = itsPolymorphicTypeMap.find( name );
     402     1305949 :         if( id == itsPolymorphicTypeMap.end() )
     403      105903 :         {
     404      270303 :           auto polyId = itsCurrentPolymorphicTypeId++;
     405      779504 :           itsPolymorphicTypeMap.insert( {name, polyId} );
     406      595804 :           return polyId | detail::msb_32bit; // mask MSB to be 1
     407      117679 :         }
     408      124079 :         else
     409     2600402 :           return id->second;
     410     2684740 :       }
     411      230201 : 
     412      170849 :     private:
     413      643441 :       //! Serializes data after calling prologue, then calls epilogue
     414      608789 :       template <class T> inline
     415      217201 :       void process( T && head )
     416      543868 :       {
     417      779779 :         prologue( *self, head );
     418      440177 :         self->processImpl( head );
     419      135864 :         epilogue( *self, head );
     420      137966 :       }
     421       99003 : 
     422       97511 :       //! Unwinds to process all data
     423      107785 :       template <class T, class ... Other> inline
     424      266879 :       void process( T && head, Other && ... tail )
     425      266199 :       {
     426      150086 :         self->process( std::forward<T>( head ) );
     427      131891 :         self->process( std::forward<Other>( tail )... );
     428      130097 :       }
     429      130461 : 
     430      103461 :       //! Serialization of a virtual_base_class wrapper
     431      123469 :       /*! \sa virtual_base_class */
     432      126641 :       template <class T> inline
     433      126153 :       ArchiveType & processImpl(virtual_base_class<T> const & b)
     434      108053 :       {
     435      277932 :         traits::detail::base_class_id id(b.base_ptr);
     436      275896 :         if(itsBaseClassSet.count(id) == 0)
     437      106528 :         {
     438      125550 :           itsBaseClassSet.insert(id);
     439      105134 :           self->processImpl( *b.base_ptr );
     440      134523 :         }
     441      152385 :         return *self;
     442      135287 :       }
     443      116929 : 
     444      117170 :       //! Serialization of a base_class wrapper
     445      102674 :       /*! \sa base_class */
     446      106674 :       template <class T> inline
     447      258970 :       ArchiveType & processImpl(base_class<T> const & b)
     448      289474 :       {
     449      125772 :         self->processImpl( *b.base_ptr );
     450      103859 :         return *self;
     451      103359 :       }
     452      125436 : 
     453      218656 :       std::vector<std::function<void(void)>> itsDeferments;
     454      201852 : 
     455      131820 :       template <class T> inline
     456      121820 :       ArchiveType & processImpl(DeferredData<T> const & d)
     457       87499 :       {
     458      219203 :         std::function<void(void)> deferment( [=](){ self->process( d.value ); } );
     459      575637 :         itsDeferments.emplace_back( std::move(deferment) );
     460      851449 : 
     461      451047 :         return *self;
     462       76002 :       }
     463       67606 : 
     464       55995 :       //! Helper macro that expands the requirements for activating an overload
     465       57101 :       /*! Requirements:
     466      410235 :             Has the requested serialization function
     467      227230 :             Does not have version and unversioned at the same time
     468      568306 :             Is output serializable AND
     469      454304 :               is specialized for this type of function OR
     470     3438194 :               has no specialization at all */
     471     3436870 :       #define PROCESS_IF(name)                                                             \
     472      133379 :       traits::EnableIf<traits::has_##name<T, ArchiveType>::value,                          \
     473      105781 :                        !traits::has_invalid_output_versioning<T, ArchiveType>::value,      \
     474      105679 :                        (traits::is_output_serializable<T, ArchiveType>::value &&           \
     475      106278 :                         (traits::is_specialized_##name<T, ArchiveType>::value ||           \
     476      152797 :                          !traits::is_specialized<T, ArchiveType>::value))> = traits::sfinae
     477      124895 : 
     478       95997 :       //! Member serialization
     479       93783 :       template <class T, PROCESS_IF(member_serialize)> inline
     480       87266 :       ArchiveType & processImpl(T const & t)
     481      116027 :       {
     482     3395914 :         access::member_serialize(*self, const_cast<T &>(t));
     483       96765 :         return *self;
     484     3404411 :       }
     485     3416214 : 
     486      399691 :       //! Non member serialization
     487      412013 :       template <class T, PROCESS_IF(non_member_serialize)> inline
     488      136475 :       ArchiveType & processImpl(T const & t)
     489      146386 :       {
     490      105017 :         CEREAL_SERIALIZE_FUNCTION_NAME(*self, const_cast<T &>(t));
     491      133406 :         return *self;
     492      301532 :       }
     493      181333 : 
     494      205411 :       //! Member split (save)
     495      225902 :       template <class T, PROCESS_IF(member_save)> inline
     496      134737 :       ArchiveType & processImpl(T const & t)
     497      205132 :       {
     498      117060 :         access::member_save(*self, t);
     499      205753 :         return *self;
     500      364098 :       }
     501      316601 : 
     502      266599 :       //! Non member split (save)
     503      226918 :       template <class T, PROCESS_IF(non_member_save)> inline
     504      532174 :       ArchiveType & processImpl(T const & t)
     505      480886 :       {
     506      460572 :         CEREAL_SAVE_FUNCTION_NAME(*self, t);
     507      205344 :         return *self;
     508      450118 :       }
     509      885864 : 
     510      227073 :       //! Member split (save_minimal)
     511      476237 :       template <class T, PROCESS_IF(member_save_minimal)> inline
     512      539238 :       ArchiveType & processImpl(T const & t)
     513     3441289 :       {
     514     3550014 :         self->process( access::member_save_minimal(*self, t) );
     515      238675 :         return *self;
     516      140126 :       }
     517      134020 : 
     518      313427 :       //! Non member split (save_minimal)
     519      363782 :       template <class T, PROCESS_IF(non_member_save_minimal)> inline
     520      375869 :       ArchiveType & processImpl(T const & t)
     521      353269 :       {
     522      232396 :         self->process( CEREAL_SAVE_MINIMAL_FUNCTION_NAME(*self, t) );
     523      235041 :         return *self;
     524      483747 :       }
     525     3760003 : 
     526      148706 :       //! Empty class specialization
     527     3453850 :       template <class T, traits::EnableIf<(Flags & AllowEmptyClassElision),
     528     3442958 :                                           !traits::is_output_serializable<T, ArchiveType>::value,
     529      427633 :                                           std::is_empty<T>::value> = traits::sfinae> inline
     530      435583 :       ArchiveType & processImpl(T const &)
     531      158032 :       {
     532      153937 :         return *self;
     533      153650 :       }
     534      217875 : 
     535      374141 :       //! No matching serialization
     536      409302 :       /*! Invalid if we have invalid output versioning or
     537      424526 :           we are not output serializable, and either
     538      634082 :           don't allow empty class ellision or allow it but are not serializing an empty class */
     539      149465 :       template <class T, traits::EnableIf<traits::has_invalid_output_versioning<T, ArchiveType>::value ||
     540      616502 :                                           (!traits::is_output_serializable<T, ArchiveType>::value &&
     541      537268 :                                            (!(Flags & AllowEmptyClassElision) || ((Flags & AllowEmptyClassElision) && !std::is_empty<T>::value)))> = traits::sfinae> inline
     542      319904 :       ArchiveType & processImpl(T const &)
     543      476284 :       {
     544      315217 :         static_assert(traits::detail::count_output_serializers<T, ArchiveType>::value != 0,
     545      235668 :             "cereal could not find any output serialization functions for the provided type and archive combination. \n\n "
     546      145270 :             "Types must either have a serialize function, load/save pair, or load_minimal/save_minimal pair (you may not mix these). \n "
     547      512503 :             "Serialize functions generally have the following signature: \n\n "
     548      668823 :             "template<class Archive> \n "
     549      648721 :             "  void serialize(Archive & ar) \n "
     550      244988 :             "  { \n "
     551      488967 :             "    ar( member1, member2, member3 ); \n "
     552      558843 :             "  } \n\n " );
     553      251833 : 
     554      142847 :         static_assert(traits::detail::count_output_serializers<T, ArchiveType>::value < 2,
     555      215447 :             "cereal found more than one compatible output serialization function for the provided type and archive combination. \n\n "
     556      125921 :             "Types must either have a serialize function, load/save pair, or load_minimal/save_minimal pair (you may not mix these). \n "
     557      229677 :             "Use specialization (see access.hpp) if you need to disambiguate between serialize vs load/save functions.  \n "
     558      218432 :             "Note that serialization functions can be inherited which may lead to the aforementioned ambiguities. \n "
     559      113416 :             "In addition, you may not mix versioned with non-versioned serialization functions. \n\n ");
     560      126161 : 
     561      301664 :         return *self;
     562      296575 :       }
     563      328306 : 
     564      324115 :       //! Registers a class version with the archive and serializes it if necessary
     565      213443 :       /*! If this is the first time this class has been serialized, we will record its
     566      221999 :           version number and serialize that.
     567      451087 : 
     568      429940 :           @tparam T The type of the class being serialized */
     569      115674 :       template <class T> inline
     570      108903 :       std::uint32_t registerClassVersion()
     571      112308 :       {
     572      185504 :         static const auto hash = std::type_index(typeid(T)).hash_code();
     573      194831 :         const auto insertResult = itsVersionedTypes.insert( hash );
     574      143823 :         const auto lock = detail::StaticObject<detail::Versions>::lock();
     575      134726 :         const auto version =
     576      128982 :           detail::StaticObject<detail::Versions>::getInstance().find( hash, detail::Version<T>::version );
     577      183293 : 
     578      177448 :         if( insertResult.second ) // insertion took place, serialize the version number
     579      308373 :           process( make_nvp<ArchiveType>("cereal_class_version", version) );
     580      289424 : 
     581      499192 :         return version;
     582      108293 :       }
     583      485068 : 
     584      484663 :       //! Member serialization
     585      178871 :       /*! Versioning implementation */
     586      179869 :       template <class T, PROCESS_IF(member_versioned_serialize)> inline
     587       97106 :       ArchiveType & processImpl(T const & t)
     588       95108 :       {
     589       85203 :         access::member_serialize(*self, const_cast<T &>(t), registerClassVersion<T>());
     590       85024 :         return *self;
     591      252577 :       }
     592      233947 : 
     593       84672 :       //! Non member serialization
     594       85852 :       /*! Versioning implementation */
     595       74194 :       template <class T, PROCESS_IF(non_member_versioned_serialize)> inline
     596       73130 :       ArchiveType & processImpl(T const & t)
     597       53701 :       {
     598       82843 :         CEREAL_SERIALIZE_FUNCTION_NAME(*self, const_cast<T &>(t), registerClassVersion<T>());
     599       83601 :         return *self;
     600       66404 :       }
     601       73407 : 
     602      785361 :       //! Member split (save)
     603       87057 :       /*! Versioning implementation */
     604      821550 :       template <class T, PROCESS_IF(member_versioned_save)> inline
     605      792618 :       ArchiveType & processImpl(T const & t)
     606       76006 :       {
     607       45619 :         access::member_save(*self, t, registerClassVersion<T>());
     608       86718 :         return *self;
     609       85711 :       }
     610       45170 : 
     611       53262 :       //! Non member split (save)
     612       34016 :       /*! Versioning implementation */
     613       55756 :       template <class T, PROCESS_IF(non_member_versioned_save)> inline
     614       55454 :       ArchiveType & processImpl(T const & t)
     615      114109 :       {
     616      141680 :         CEREAL_SAVE_FUNCTION_NAME(*self, t, registerClassVersion<T>());
     617       63174 :         return *self;
     618       92960 :       }
     619       55359 : 
     620       53665 :       //! Member split (save_minimal)
     621       72672 :       /*! Versioning implementation */
     622       34959 :       template <class T, PROCESS_IF(member_versioned_save_minimal)> inline
     623       55057 :       ArchiveType & processImpl(T const & t)
     624       45554 :       {
     625       35806 :         self->process( access::member_save_minimal(*self, t, registerClassVersion<T>()) );
     626       55406 :         return *self;
     627      115603 :       }
     628       45206 : 
     629      136003 :       //! Non member split (save_minimal)
     630      116706 :       /*! Versioning implementation */
     631       59206 :       template <class T, PROCESS_IF(non_member_versioned_save_minimal)> inline
     632      204403 :       ArchiveType & processImpl(T const & t)
     633       59304 :       {
     634      238050 :         self->process( CEREAL_SAVE_MINIMAL_FUNCTION_NAME(*self, t, registerClassVersion<T>()) );
     635      198304 :         return *self;
     636       37751 :       }
     637      204652 : 
     638       41003 :     #undef PROCESS_IF
     639      213652 : 
     640      199605 :     private:
     641       58250 :       ArchiveType * const self;
     642      223550 : 
     643       49303 :       //! A set of all base classes that have been serialized
     644      243458 :       std::unordered_set<traits::detail::base_class_id, traits::detail::base_class_id_hash> itsBaseClassSet;
     645      952007 : 
     646       61362 :       //! Maps from addresses to pointer ids
     647      960360 :       std::unordered_map<void const *, std::uint32_t> itsSharedPointerMap;
     648      771904 : 
     649      225506 :       //! The id to be given to the next pointer
     650      205405 :       std::uint32_t itsCurrentPointerId;
     651       77005 : 
     652      227705 :       //! Maps from polymorphic type name strings to ids
     653       36504 :       std::unordered_map<char const *, std::uint32_t> itsPolymorphicTypeMap;
     654      336051 : 
     655      295603 :       //! The id to be given to the next polymorphic type name
     656      410250 :       std::uint32_t itsCurrentPolymorphicTypeId;
     657      374350 : 
     658       55003 :       //! Keeps track of classes that have versioning information associated with them
     659       85690 :       std::unordered_set<size_type> itsVersionedTypes;
     660       19190 :   }; // class OutputArchive
     661       74264 : 
     662      213005 :   // ######################################################################
     663       62364 :   //! The base input archive class
     664      261821 :   /*! This is the base input archive for all input archives.  If you create
     665      194005 :       a custom archive class, it should derive from this, passing itself as
     666       74860 :       a template parameter for the ArchiveType.
     667      214658 : 
     668       64705 :       The base class provides all of the functionality necessary to
     669      264906 :       properly forward data to the correct serialization functions.
     670      284303 : 
     671       65006 :       Individual archives should use a combination of prologue and
     672      227704 :       epilogue functions together with specializations of serialize, save,
     673      234705 :       and load to alter the functionality of their serialization.
     674      416306 : 
     675      539803 :       @tparam ArchiveType The archive type that derives from InputArchive
     676       76104 :       @tparam Flags Flags to control advanced functionality.  See the Flags
     677      323704 :                     enum for more information.
     678      231402 :       @ingroup Internal */
     679      164303 :   template<class ArchiveType, std::uint32_t Flags = 0>
     680      302302 :   class InputArchive : public detail::InputArchiveBase
     681       47902 :   {
     682      318303 :     public:
     683      226002 :       //! Construct the output archive
     684      140804 :       /*! @param derived A pointer to the derived ArchiveType (pass this from the derived archive) */
     685      298202 :       InputArchive(ArchiveType * const derived) :
     686       70103 :         self(derived),
     687      312130 :         itsBaseClassSet(),
     688      242626 :         itsSharedPointerMap(),
     689      162630 :         itsPolymorphicTypeMap(),
     690      293828 :         itsVersionedTypes()
     691       68203 :       { }
     692      307305 : 
     693      247702 :       InputArchive & operator=( InputArchive const & ) = delete;
     694      174705 : 
     695      295803 :       //! Serializes all passed in data
     696       55803 :       /*! This is the primary interface for serializing data with an archive */
     697      505205 :       template <class ... Types> inline
     698     2153302 :       ArchiveType & operator()( Types && ... args )
     699      583252 :       {
     700     2392351 :         process( std::forward<Types>( args )... );
     701     1932402 :         return *self;
     702       72003 :       }
     703       61702 : 
     704       69204 :       //! Serializes any data marked for deferment
     705      228326 :       /*! This will cause any data wrapped in DeferredData to be immediately serialized
     706       84927 :           @relates defer */
     707      325029 :       void serializeDeferments()
     708      254726 :       {
     709      164605 :         for( auto & deferment : itsDeferments )
     710      632959 :           deferment();
     711      134503 :       }
     712      660961 : 
     713      571558 :       /*! @name Boost Transition Layer
     714      193605 :           Functionality that mirrors the syntax for Boost.  This is useful if you are transitioning
     715      288972 :           a large project from Boost to cereal.  The preferred interface for cereal is using operator(). */
     716      203303 :       //! @{
     717      515222 : 
     718      424195 :       //! Indicates this archive is intended for loading
     719      172980 :       /*! This ensures compatibility with boost archive types.  If you are transitioning
     720      268153 :           from boost, you can check this value within a member or external serialize function
     721      119801 :           (i.e., Archive::is_loading::value) to enable behavior specific to loading, until
     722     1145585 :           you can transition to split save/load or save_minimal/load_minimal functions */
     723      184651 :       using is_loading = std::true_type;
     724     1063084 : 
     725     1186300 :       //! Indicates this archive is not intended for saving
     726       96212 :       /*! This ensures compatibility with boost archive types.  If you are transitioning
     727      236598 :           from boost, you can check this value within a member or external serialize function
     728      169128 :           (i.e., Archive::is_saving::value) to disable behavior specific to loading, until
     729      157092 :           you can transition to split save/load or save_minimal/load_minimal functions */
     730      258392 :       using is_saving = std::false_type;
     731      106812 : 
     732      197837 :       //! Serializes passed in data
     733      187701 :       /*! This is a boost compatability layer and is not the preferred way of using
     734       76736 :           cereal.  If you are transitioning from boost, use this until you can
     735      161369 :           transition to the operator() overload */
     736       76423 :       template <class T> inline
     737      250937 :       ArchiveType & operator&( T && arg )
     738     2015856 :       {
     739      173125 :         self->process( std::forward<T>( arg ) );
     740     2191504 :         return *self;
     741     3791623 :       }
     742      347062 : 
     743     2162958 :       //! Serializes passed in data
     744     2034006 :       /*! This is a boost compatability layer and is not the preferred way of using
     745      202123 :           cereal.  If you are transitioning from boost, use this until you can
     746      498907 :           transition to the operator() overload */
     747      169821 :       template <class T> inline
     748      445818 :       ArchiveType & operator>>( T && arg )
     749      520801 :       {
     750      349135 :         self->process( std::forward<T>( arg ) );
     751      207803 :         return *self;
     752      573185 :       }
     753      851264 : 
     754      198200 :       //! @}
     755      583375 : 
     756      412881 :       //! Retrieves a shared pointer given a unique key for it
     757      266305 :       /*! This is used to retrieve a previously registered shared_ptr
     758      243054 :           which has already been loaded.
     759      193381 : 
     760      325149 :           @internal
     761      155364 :           @param id The unique id that was serialized for the pointer
     762      171978 :           @return A shared pointer to the data
     763      244694 :           @throw Exception if the id does not exist */
     764      102146 :       inline std::shared_ptr<void> getSharedPointer(std::uint32_t const id)
     765     1089662 :       {
     766      149377 :         if(id == 0) return std::shared_ptr<void>(nullptr);
     767     1053419 : 
     768     1146888 :         auto iter = itsSharedPointerMap.find( id );
     769       82154 :         if(iter == itsSharedPointerMap.end())
     770      198223 :           throw Exception("Error while trying to deserialize a smart pointer. Could not find id " + std::to_string(id));
     771      137472 : 
     772      147366 :         return iter->second;
     773      236651 :       }
     774       97515 : 
     775      150872 :       //! Registers a shared pointer to its unique identifier
     776      158014 :       /*! After a shared pointer has been allocated for the first time, it should
     777       88460 :           be registered with its loaded id for future references to it.
     778      100724 : 
     779       87189 :           @internal
     780      179987 :           @param id The unique identifier for the shared pointer
     781     1934067 :           @param ptr The actual shared pointer */
     782      147690 :       inline void registerSharedPointer(std::uint32_t const id, std::shared_ptr<void> ptr)
     783     2083012 :       {
     784     1920157 :         std::uint32_t const stripped_id = id & ~detail::msb_32bit;
     785      244287 :         itsSharedPointerMap[stripped_id] = ptr;
     786      164130 :       }
     787      187334 : 
     788      297492 :       //! Retrieves the string for a polymorphic type given a unique key for it
     789      511006 :       /*! This is used to retrieve a string previously registered during
     790      246802 :           a polymorphic load.
     791      469420 : 
     792      506985 :           @internal
     793      315847 :           @param id The unique id that was serialized for the polymorphic type
     794      226207 :           @return The string identifier for the tyep */
     795      592637 :       inline std::string getPolymorphicName(std::uint32_t const id)
     796      481344 :       {
     797      137097 :         auto name = itsPolymorphicTypeMap.find( id );
     798      217416 :         if(name == itsPolymorphicTypeMap.end())
     799       59907 :         {
     800      156423 :           throw Exception("Error while trying to deserialize a polymorphic pointer. Could not find type id " + std::to_string(id));
     801      113209 :         }
     802      125009 :         return name->second;
     803      235494 :       }
     804       85016 : 
     805      105642 :       //! Registers a polymorphic name string to its unique identifier
     806      145491 :       /*! After a polymorphic type has been loaded for the first time, it should
     807       55571 :           be registered with its loaded id for future references to it.
     808      125557 : 
     809       85408 :           @internal
     810       67279 :           @param id The unique identifier for the polymorphic type
     811      127386 :           @param name The name associated with the tyep */
     812       36902 :       inline void registerPolymorphicName(std::uint32_t const id, std::string const & name)
     813      135825 :       {
     814      598503 :         std::uint32_t const stripped_id = id & ~detail::msb_32bit;
     815      105713 :         itsPolymorphicTypeMap.insert( {stripped_id, name} );
     816      645937 :       }
     817      546609 : 
     818      626682 :     private:
     819      586519 :       //! Serializes data after calling prologue, then calls epilogue
     820      116203 :       template <class T> inline
     821       85377 :       void process( T && head )
     822       73727 :       {
     823      127791 :         prologue( *self, head );
     824       36107 :         self->processImpl( head );
     825       93186 :         epilogue( *self, head );
     826      144396 :       }
     827       34220 : 
     828      152200 :       //! Unwinds to process all data
     829       94609 :       template <class T, class ... Other> inline
     830      114553 :       void process( T && head, Other && ... tail )
     831      143983 :       {
     832       75578 :         process( std::forward<T>( head ) );
     833      125849 :         process( std::forward<Other>( tail )... );
     834       96109 :       }
     835       96287 : 
     836      104787 :       //! Serialization of a virtual_base_class wrapper
     837      115508 :       /*! \sa virtual_base_class */
     838      165307 :       template <class T> inline
     839       93803 :       ArchiveType & processImpl(virtual_base_class<T> & b)
     840       74808 :       {
     841       86491 :         traits::detail::base_class_id id(b.base_ptr);
     842       36100 :         if(itsBaseClassSet.count(id) == 0)
     843       85589 :         {
     844       83200 :           itsBaseClassSet.insert(id);
     845       74276 :           self->processImpl( *b.base_ptr );
     846      120208 :         }
     847       43826 :         return *self;
     848      120124 :       }
     849      120932 : 
     850      109413 :       //! Serialization of a base_class wrapper
     851       92614 :       /*! \sa base_class */
     852       51426 :       template <class T> inline
     853       73714 :       ArchiveType & processImpl(base_class<T> & b)
     854       66229 :       {
     855       64614 :         self->processImpl( *b.base_ptr );
     856       76215 :         return *self;
     857       27907 :       }
     858       85601 : 
     859       66915 :       std::vector<std::function<void(void)>> itsDeferments;
     860     5275176 : 
     861       77312 :       template <class T> inline
     862     5273595 :       ArchiveType & processImpl(DeferredData<T> const & d)
     863     5312838 :       {
     864     5283019 :         std::function<void(void)> deferment( [=](){ self->process( d.value ); } );
     865     5289468 :         itsDeferments.emplace_back( std::move(deferment) );
     866       84182 : 
     867       41601 :         return *self;
     868       92692 :       }
     869       74906 : 
     870       66824 :       //! Helper macro that expands the requirements for activating an overload
     871       74308 :       /*! Requirements:
     872      147023 :             Has the requested serialization function
     873      108196 :             Does not have version and unversioned at the same time
     874      173108 :             Is input serializable AND
     875      196715 :               is specialized for this type of function OR
     876      165386 :               has no specialization at all */
     877      171841 :       #define PROCESS_IF(name)                                                              \
     878      167041 :       traits::EnableIf<traits::has_##name<T, ArchiveType>::value,                           \
     879       61707 :                        !traits::has_invalid_input_versioning<T, ArchiveType>::value,        \
     880      160477 :                        (traits::is_input_serializable<T, ArchiveType>::value &&             \
     881      124806 :                         (traits::is_specialized_##name<T, ArchiveType>::value ||            \
     882      157077 :                          !traits::is_specialized<T, ArchiveType>::value))> = traits::sfinae
     883      164024 : 
     884     1013006 :       //! Member serialization
     885       66429 :       template <class T, PROCESS_IF(member_serialize)> inline
     886      993955 :       ArchiveType & processImpl(T & t)
     887     1003229 :       {
     888     1028831 :         access::member_serialize(*self, t);
     889      990207 :         return *self;
     890       50811 :       }
     891       24704 : 
     892      116718 :       //! Non member serialization
     893       69608 :       template <class T, PROCESS_IF(non_member_serialize)> inline
     894      102914 :       ArchiveType & processImpl(T & t)
     895      122099 :       {
     896       98506 :         CEREAL_SERIALIZE_FUNCTION_NAME(*self, t);
     897      127296 :         return *self;
     898      110892 :       }
     899       69665 : 
     900       77966 :       //! Member split (load)
     901       55407 :       template <class T, PROCESS_IF(member_load)> inline
     902       50611 :       ArchiveType & processImpl(T & t)
     903       51682 :       {
     904       71513 :         access::member_load(*self, t);
     905       90488 :         return *self;
     906     4762483 :       }
     907       65354 : 
     908     4790982 :       //! Non member split (load)
     909     4770154 :       template <class T, PROCESS_IF(non_member_load)> inline
     910     4790432 :       ArchiveType & processImpl(T & t)
     911     4760430 :       {
     912       55654 :         CEREAL_LOAD_FUNCTION_NAME(*self, t);
     913       64328 :         return *self;
     914       45605 :       }
     915       55027 : 
     916       35628 :       //! Member split (load_minimal)
     917       26407 :       template <class T, PROCESS_IF(member_load_minimal)> inline
     918      144675 :       ArchiveType & processImpl(T & t)
     919       26057 :       {
     920      127270 :         using OutArchiveType = typename traits::detail::get_output_from_input<ArchiveType>::type;
     921      106321 :         typename traits::has_member_save_minimal<T, OutArchiveType>::type value;
     922      172789 :         self->process( value );
     923      132731 :         access::member_load_minimal(*self, t, value);
     924      151190 :         return *self;
     925       98319 :       }
     926      124381 : 
     927      162707 :       //! Non member split (load_minimal)
     928      135887 :       template <class T, PROCESS_IF(non_member_load_minimal)> inline
     929      144654 :       ArchiveType & processImpl(T & t)
     930     1025255 :       {
     931       23333 :         using OutArchiveType = typename traits::detail::get_output_from_input<ArchiveType>::type;
     932     1018319 :         typename traits::has_non_member_save_minimal<T, OutArchiveType>::type value;
     933      983741 :         self->process( value );
     934     1002555 :         CEREAL_LOAD_MINIMAL_FUNCTION_NAME(*self, t, value);
     935     1043256 :         return *self;
     936       22025 :       }
     937       89640 : 
     938       63500 :       //! Empty class specialization
     939       59406 :       template <class T, traits::EnableIf<(Flags & AllowEmptyClassElision),
     940       98171 :                                           !traits::is_input_serializable<T, ArchiveType>::value,
     941       57322 :                                           std::is_empty<T>::value> = traits::sfinae> inline
     942       86807 :       ArchiveType & processImpl(T const &)
     943       83408 :       {
     944      173056 :         return *self;
     945      103907 :       }
     946     2566558 : 
     947      126653 :       //! No matching serialization
     948     2598605 :       /*! Invalid if we have invalid input versioning or
     949     2528858 :           we are not input serializable, and either
     950       92503 :           don't allow empty class ellision or allow it but are not serializing an empty class */
     951       91308 :       template <class T, traits::EnableIf<traits::has_invalid_input_versioning<T, ArchiveType>::value ||
     952       57810 :                                           (!traits::is_input_serializable<T, ArchiveType>::value &&
     953       76155 :                                            (!(Flags & AllowEmptyClassElision) || ((Flags & AllowEmptyClassElision) && !std::is_empty<T>::value)))> = traits::sfinae> inline
     954       55611 :       ArchiveType & processImpl(T const &)
     955       75709 :       {
     956      602154 :         static_assert(traits::detail::count_input_serializers<T, ArchiveType>::value != 0,
     957       56906 :             "cereal could not find any input serialization functions for the provided type and archive combination. \n\n "
     958      614708 :             "Types must either have a serialize function, load/save pair, or load_minimal/save_minimal pair (you may not mix these). \n "
     959      592158 :             "Serialize functions generally have the following signature: \n\n "
     960      593061 :             "template<class Archive> \n "
     961      581511 :             "  void serialize(Archive & ar) \n "
     962        6605 :             "  { \n "
     963       37212 :             "    ar( member1, member2, member3 ); \n "
     964       26211 :             "  } \n\n " );
     965       74786 : 
     966       47012 :         static_assert(traits::detail::count_input_serializers<T, ArchiveType>::value < 2,
     967       74437 :             "cereal found more than one compatible input serialization function for the provided type and archive combination. \n\n "
     968      112886 :             "Types must either have a serialize function, load/save pair, or load_minimal/save_minimal pair (you may not mix these). \n "
     969       37012 :             "Use specialization (see access.hpp) if you need to disambiguate between serialize vs load/save functions.  \n "
     970      142991 :             "Note that serialization functions can be inherited which may lead to the aforementioned ambiguities. \n "
     971       53956 :             "In addition, you may not mix versioned with non-versioned serialization functions. \n\n ");
     972      127236 : 
     973      153066 :         return *self;
     974       94604 :       }
     975      135684 : 
     976      106283 :       //! Befriend for versioning in load_and_construct
     977       79796 :       template <class A, class B, bool C, bool D, bool E, bool F> friend struct detail::Construct;
     978      188971 : 
     979       85644 :       //! Registers a class version with the archive and serializes it if necessary
     980      188374 :       /*! If this is the first time this class has been serialized, we will record its
     981      131168 :           version number and serialize that.
     982      118790 : 
     983      103420 :           @tparam T The type of the class being serialized */
     984       81924 :       template <class T> inline
     985      127324 :       std::uint32_t loadClassVersion()
     986       96239 :       {
     987      106414 :         static const auto hash = std::type_index(typeid(T)).hash_code();
     988      158315 :         auto lookupResult = itsVersionedTypes.find( hash );
     989     2474218 : 
     990      267424 :         if( lookupResult != itsVersionedTypes.end() ) // already exists
     991     2553222 :           return lookupResult->second;
     992     2632572 :         else // need to load
     993      296784 :         {
     994      204469 :           std::uint32_t version;
     995      166823 : 
     996      125493 :           process( make_nvp<ArchiveType>("cereal_class_version", version) );
     997       87903 :           itsVersionedTypes.emplace_hint( lookupResult, hash, version );
     998      137793 : 
     999       93190 :           return version;
    1000       86413 :         }
    1001       86058 :       }
    1002      641412 : 
    1003      107066 :       //! Member serialization
    1004      653064 :       /*! Versioning implementation */
    1005      651163 :       template <class T, PROCESS_IF(member_versioned_serialize)> inline
    1006      641368 :       ArchiveType & processImpl(T & t)
    1007      580983 :       {
    1008       86316 :         const auto version = loadClassVersion<T>();
    1009       74593 :         access::member_serialize(*self, t, version);
    1010       96492 :         return *self;
    1011       97311 :       }
    1012       56999 : 
    1013      108028 :       //! Non member serialization
    1014       87899 :       /*! Versioning implementation */
    1015       95123 :       template <class T, PROCESS_IF(non_member_versioned_serialize)> inline
    1016      154835 :       ArchiveType & processImpl(T & t)
    1017       55747 :       {
    1018      185759 :         const auto version = loadClassVersion<T>();
    1019      105996 :         CEREAL_SERIALIZE_FUNCTION_NAME(*self, t, version);
    1020      176899 :         return *self;
    1021      205613 :       }
    1022      195204 : 
    1023      155625 :       //! Member split (load)
    1024      286604 :       /*! Versioning implementation */
    1025      226061 :       template <class T, PROCESS_IF(member_versioned_load)> inline
    1026      275121 :       ArchiveType & processImpl(T & t)
    1027      218694 :       {
    1028      539170 :         const auto version = loadClassVersion<T>();
    1029      109407 :         access::member_load(*self, t, version);
    1030      498320 :         return *self;
    1031      513487 :       }
    1032      452405 : 
    1033      592940 :       //! Non member split (load)
    1034      481651 :       /*! Versioning implementation */
    1035      142217 :       template <class T, PROCESS_IF(non_member_versioned_load)> inline
    1036      616086 :       ArchiveType & processImpl(T & t)
    1037      431842 :       {
    1038      552085 :         const auto version = loadClassVersion<T>();
    1039      510925 :         CEREAL_LOAD_FUNCTION_NAME(*self, t, version);
    1040      514681 :         return *self;
    1041      150629 :       }
    1042      526329 : 
    1043      512120 :       //! Member split (load_minimal)
    1044      564905 :       /*! Versioning implementation */
    1045      599221 :       template <class T, PROCESS_IF(member_versioned_load_minimal)> inline
    1046      132628 :       ArchiveType & processImpl(T & t)
    1047      123303 :       {
    1048      168114 :         using OutArchiveType = typename traits::detail::get_output_from_input<ArchiveType>::type;
    1049      127010 :         const auto version = loadClassVersion<T>();
    1050      137893 :         typename traits::has_member_versioned_save_minimal<T, OutArchiveType>::type value;
    1051      126826 :         self->process(value);
    1052       67608 :         access::member_load_minimal(*self, t, value, version);
    1053      124798 :         return *self;
    1054      143742 :       }
    1055       81818 : 
    1056      164625 :       //! Non member split (load_minimal)
    1057      139889 :       /*! Versioning implementation */
    1058      319911 :       template <class T, PROCESS_IF(non_member_versioned_load_minimal)> inline
    1059      119908 :       ArchiveType & processImpl(T & t)
    1060      291298 :       {
    1061      310013 :         using OutArchiveType = typename traits::detail::get_output_from_input<ArchiveType>::type;
    1062      235594 :         const auto version = loadClassVersion<T>();
    1063      356205 :         typename traits::has_non_member_versioned_save_minimal<T, OutArchiveType>::type value;
    1064      247803 :         self->process(value);
    1065       96998 :         CEREAL_LOAD_MINIMAL_FUNCTION_NAME(*self, t, value, version);
    1066      275113 :         return *self;
    1067      166009 :       }
    1068      374613 : 
    1069      225010 :       #undef PROCESS_IF
    1070      410803 : 
    1071      218205 :     private:
    1072      317083 :       ArchiveType * const self;
    1073      395109 : 
    1074      652696 :       //! A set of all base classes that have been serialized
    1075      281825 :       std::unordered_set<traits::detail::base_class_id, traits::detail::base_class_id_hash> itsBaseClassSet;
    1076      662502 : 
    1077      437408 :       //! Maps from pointer ids to metadata
    1078      641818 :       std::unordered_map<std::uint32_t, std::shared_ptr<void>> itsSharedPointerMap;
    1079      571700 : 
    1080      594736 :       //! Maps from name ids to names
    1081      273504 :       std::unordered_map<std::uint32_t, std::string> itsPolymorphicTypeMap;
    1082      934952 : 
    1083      478838 :       //! Maps from type hash codes to version numbers
    1084      971319 :       std::unordered_map<std::size_t, std::uint32_t> itsVersionedTypes;
    1085     1047497 :   }; // class InputArchive
    1086      993604 : } // namespace cereal
    1087      660919 : 
    1088      550604 : // This include needs to come after things such as binary_data, make_nvp, etc
    1089      430517 : #include "cereal/types/common.hpp"
    1090      499020 : 
    1091      500477 : #endif // CEREAL_CEREAL_HPP_

Generated by: LCOV version 1.13