LCOV - code coverage report

Current view: | top level - cereal/types - base_class.hpp (source / functions) |  |  | Hit | Total | Coverage
Test: | coverage.info |  | Lines: | 10 | 10 | 100.0 %
Date: | 2022-01-16 21:05:07 |  | Functions: | 10 | 10 | 100.0 %

              Line data    Source code

           1             : /*! \file base_class.hpp
           2             :     \brief Support for base classes (virtual and non-virtual)
           3             :     \ingroup OtherTypes */
           4             : /*
           5             :   Copyright (c) 2014, Randolph Voorhies, Shane Grant
           6             :   All rights reserved.
           7             :
           8             :   Redistribution and use in source and binary forms, with or without
           9             :   modification, are permitted provided that the following conditions are met:
          10             :       * Redistributions of source code must retain the above copyright
          11             :         notice, this list of conditions and the following disclaimer.
          12             :       * Redistributions in binary form must reproduce the above copyright
          13             :         notice, this list of conditions and the following disclaimer in the
          14             :         documentation and/or other materials provided with the distribution.
          15             :       * Neither the name of the copyright holder nor the
          16             :         names of its contributors may be used to endorse or promote products
          17             :         derived from this software without specific prior written permission.
          18             :
          19             :   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
          20             :   ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
          21             :   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
          22             :   DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
          23             :   DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
          24             :   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
          25             :   LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
          26             :   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
          27             :   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
          28             :   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
          29             : */
          30             : #ifndef CEREAL_TYPES_BASE_CLASS_HPP_
          31             : #define CEREAL_TYPES_BASE_CLASS_HPP_
          32             :
          33             : #include "cereal/details/traits.hpp"
          34             : #include "cereal/details/polymorphic_impl_fwd.hpp"
          35             :
          36             : namespace cereal
          37             : {
          38             :   namespace base_class_detail
          39             :   {
          40             :     //! Used to register polymorphic relations and avoid the need to include
          41             :     //! polymorphic.hpp when no polymorphism is used
          42             :     /*! @internal */
          43             :     template <class Base, class Derived, bool IsPolymorphic = std::is_polymorphic<Base>::value>
          44             :     struct RegisterPolymorphicBaseClass
          45             :     {
          46             :       static void bind()
          47             :       { }
          48             :     };
          49             :
          50             :     //! Polymorphic version
          51             :     /*! @internal */
          52             :     template <class Base, class Derived>
          53             :     struct RegisterPolymorphicBaseClass<Base, Derived, true>
          54             :     {
          55        9600 :       static void bind()
          56        9600 :       { detail::RegisterPolymorphicCaster<Base, Derived>::bind(); }
          57             :     };
          58             :   }
          59             :
          60             :   //! Casts a derived class to its non-virtual base class in a way that safely supports abstract classes
          61             :   /*! This should be used in cases when a derived type needs to serialize its base type. This is better than directly
          62             :       using static_cast, as it allows for serialization of pure virtual (abstract) base classes.
          63             :
          64             :       This also automatically registers polymorphic relation between the base and derived class, assuming they
          65             :       are indeed polymorphic. Note this is not the same as polymorphic type registration. For more information
          66             :       see the documentation on polymorphism. If using a polymorphic class, be sure to include support for
          67             :       polymorphism (cereal/types/polymorphic.hpp).
          68             :
          69             :       \sa virtual_base_class
          70             :
          71             :       @code{.cpp}
          72             :       struct MyBase
          73             :       {
          74             :         int x;
          75             :
          76             :         virtual void foo() = 0;
          77             :
          78             :         template <class Archive>
          79             :         void serialize( Archive & ar )
          80             :         {
          81             :           ar( x );
          82             :         }
          83             :       };
          84             :
          85             :       struct MyDerived : public MyBase //<-- Note non-virtual inheritance
          86             :       {
          87             :         int y;
          88             :
          89             :         virtual void foo() {};
          90             :
          91             :         template <class Archive>
          92             :         void serialize( Archive & ar )
          93             :         {
          94             :           ar( cereal::base_class<MyBase>(this) );
          95             :           ar( y );
          96             :         }
          97             :       };
          98             :       @endcode */
          99             :   template<class Base>
         100             :     struct base_class : private traits::detail::BaseCastBase
         101             :     {
         102             :       template<class Derived>
         103        6400 :         base_class(Derived const * derived) :
         104        6400 :           base_ptr(const_cast<Base*>(static_cast<Base const *>(derived)))
         105             :       {
         106             :         static_assert( std::is_base_of<Base, Derived>::value, "Can only use base_class on a valid base class" );
         107        6400 :         base_class_detail::RegisterPolymorphicBaseClass<Base, Derived>::bind();
         108        6400 :       }
         109             :
         110             :         Base * base_ptr;
         111             :     };
         112             :
         113             :   //! Casts a derived class to its virtual base class in a way that allows cereal to track inheritance
         114             :   /*! This should be used in cases when a derived type features virtual inheritance from some
         115             :       base type.  This allows cereal to track the inheritance and to avoid making duplicate copies
         116             :       during serialization.
         117             :
         118             :       It is safe to use virtual_base_class in all circumstances for serializing base classes, even in cases
         119             :       where virtual inheritance does not take place, though it may be slightly faster to utilize
         120             :       cereal::base_class<> if you do not need to worry about virtual inheritance.
         121             :
         122             :       This also automatically registers polymorphic relation between the base and derived class, assuming they
         123             :       are indeed polymorphic. Note this is not the same as polymorphic type registration. For more information
         124             :       see the documentation on polymorphism. If using a polymorphic class, be sure to include support for
         125             :       polymorphism (cereal/types/polymorphic.hpp).
         126             :
         127             :       \sa base_class
         128             :
         129             :       @code{.cpp}
         130             :       struct MyBase
         131             :       {
         132             :         int x;
         133             :
         134             :         template <class Archive>
         135             :         void serialize( Archive & ar )
         136             :         {
         137             :           ar( x );
         138             :         }
         139             :       };
         140             :
         141             :       struct MyLeft : virtual MyBase //<-- Note the virtual inheritance
         142             :       {
         143             :         int y;
         144             :
         145             :         template <class Archive>
         146             :         void serialize( Archive & ar )
         147             :         {
         148             :           ar( cereal::virtual_base_class<MyBase>( this ) );
         149             :           ar( y );
         150             :         }
         151             :       };
         152             :
         153             :       struct MyRight : virtual MyBase
         154             :       {
         155             :         int z;
         156             :
         157             :         template <class Archive>
         158             :         void serialize( Archive & ar )
         159             :         {
         160             :           ar( cereal::virtual_base_clas<MyBase>( this ) );
         161             :           ar( z );
         162             :         }
         163             :       };
         164             :
         165             :       // diamond virtual inheritance; contains one copy of each base class
         166             :       struct MyDerived : virtual MyLeft, virtual MyRight
         167             :       {
         168             :         int a;
         169             :
         170             :         template <class Archive>
         171             :         void serialize( Archive & ar )
         172             :         {
         173             :           ar( cereal::virtual_base_class<MyLeft>( this ) );  // safely serialize data members in MyLeft
         174             :           ar( cereal::virtual_base_class<MyRight>( this ) ); // safely serialize data members in MyRight
         175             :           ar( a );
         176             :
         177             :           // Because we used virtual_base_class, cereal will ensure that only one instance of MyBase is
         178             :           // serialized as we traverse the inheritance heirarchy. This means that there will be one copy
         179             :           // each of the variables x, y, z, and a
         180             :
         181             :           // If we had chosen to use static_cast<> instead, cereal would perform no tracking and
         182             :           // assume that every base class should be serialized (in this case leading to a duplicate
         183             :           // serialization of MyBase due to diamond inheritance
         184             :       };
         185             :      }
         186             :      @endcode */
         187             :   template<class Base>
         188             :     struct virtual_base_class : private traits::detail::BaseCastBase
         189             :     {
         190             :       template<class Derived>
         191        3200 :         virtual_base_class(Derived const * derived) :
         192        3200 :           base_ptr(const_cast<Base*>(static_cast<Base const *>(derived)))
         193             :       {
         194             :         static_assert( std::is_base_of<Base, Derived>::value, "Can only use virtual_base_class on a valid base class" );
         195        3200 :         base_class_detail::RegisterPolymorphicBaseClass<Base, Derived>::bind();
         196        3200 :       }
         197             :
         198             :         Base * base_ptr;
         199             :     };
         200             :
         201             : } // namespace cereal
         202             :
         203             : #endif // CEREAL_TYPES_BASE_CLASS_HPP_

Generated by: LCOV version 1.14