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: 2017-02-12 13:57:59 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 cereal 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 RANDOLPH VOORHIES OR SHANE GRANT 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        8000 :       static void bind()
      56        8000 :       { 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.
      67             : 
      68             :       \sa virtual_base_class
      69             : 
      70             :       @code{.cpp}
      71             :       struct MyBase
      72             :       {
      73             :         int x;
      74             : 
      75             :         virtual void foo() = 0;
      76             : 
      77             :         template <class Archive>
      78             :         void serialize( Archive & ar )
      79             :         {
      80             :           ar( x );
      81             :         }
      82             :       };
      83             : 
      84             :       struct MyDerived : public MyBase //<-- Note non-virtual inheritance
      85             :       {
      86             :         int y;
      87             : 
      88             :         virtual void foo() {};
      89             : 
      90             :         template <class Archive>
      91             :         void serialize( Archive & ar )
      92             :         {
      93             :           ar( cereal::base_class<MyBase>(this) );
      94             :           ar( y );
      95             :         }
      96             :       };
      97             :       @endcode */
      98             :   template<class Base>
      99             :     struct base_class : private traits::detail::BaseCastBase
     100             :     {
     101             :       template<class Derived>
     102        4800 :         base_class(Derived const * derived) :
     103        4800 :           base_ptr(const_cast<Base*>(static_cast<Base const *>(derived)))
     104             :       {
     105             :         static_assert( std::is_base_of<Base, Derived>::value, "Can only use base_class on a valid base class" );
     106        4800 :         base_class_detail::RegisterPolymorphicBaseClass<Base, Derived>::bind();
     107        4800 :       }
     108             : 
     109             :         Base * base_ptr;
     110             :     };
     111             : 
     112             :   //! Casts a derived class to its virtual base class in a way that allows cereal to track inheritance
     113             :   /*! This should be used in cases when a derived type features virtual inheritance from some
     114             :       base type.  This allows cereal to track the inheritance and to avoid making duplicate copies
     115             :       during serialization.
     116             : 
     117             :       It is safe to use virtual_base_class in all circumstances for serializing base classes, even in cases
     118             :       where virtual inheritance does not take place, though it may be slightly faster to utilize
     119             :       cereal::base_class<> if you do not need to worry about virtual inheritance.
     120             : 
     121             :       This also automatically registers polymorphic relation between the base and derived class, assuming they
     122             :       are indeed polymorphic. Note this is not the same as polymorphic type registration. For more information
     123             :       see the documentation on polymorphism.
     124             : 
     125             :       \sa base_class
     126             : 
     127             :       @code{.cpp}
     128             :       struct MyBase
     129             :       {
     130             :         int x;
     131             : 
     132             :         template <class Archive>
     133             :         void serialize( Archive & ar )
     134             :         {
     135             :           ar( x );
     136             :         }
     137             :       };
     138             : 
     139             :       struct MyLeft : virtual MyBase //<-- Note the virtual inheritance
     140             :       {
     141             :         int y;
     142             : 
     143             :         template <class Archive>
     144             :         void serialize( Archive & ar )
     145             :         {
     146             :           ar( cereal::virtual_base_class<MyBase>( this ) );
     147             :           ar( y );
     148             :         }
     149             :       };
     150             : 
     151             :       struct MyRight : virtual MyBase
     152             :       {
     153             :         int z;
     154             : 
     155             :         template <class Archive>
     156             :         void serialize( Archive & ar )
     157             :         {
     158             :           ar( cereal::virtual_base_clas<MyBase>( this ) );
     159             :           ar( z );
     160             :         }
     161             :       };
     162             : 
     163             :       // diamond virtual inheritance; contains one copy of each base class
     164             :       struct MyDerived : virtual MyLeft, virtual MyRight
     165             :       {
     166             :         int a;
     167             : 
     168             :         template <class Archive>
     169             :         void serialize( Archive & ar )
     170             :         {
     171             :           ar( cereal::virtual_base_class<MyLeft>( this ) );  // safely serialize data members in MyLeft
     172             :           ar( cereal::virtual_base_class<MyRight>( this ) ); // safely serialize data members in MyRight
     173             :           ar( a );
     174             : 
     175             :           // Because we used virtual_base_class, cereal will ensure that only one instance of MyBase is
     176             :           // serialized as we traverse the inheritance heirarchy. This means that there will be one copy
     177             :           // each of the variables x, y, z, and a
     178             : 
     179             :           // If we had chosen to use static_cast<> instead, cereal would perform no tracking and
     180             :           // assume that every base class should be serialized (in this case leading to a duplicate
     181             :           // serialization of MyBase due to diamond inheritance
     182             :       };
     183             :      }
     184             :      @endcode */
     185             :   template<class Base>
     186             :     struct virtual_base_class : private traits::detail::BaseCastBase
     187             :     {
     188             :       template<class Derived>
     189        3200 :         virtual_base_class(Derived const * derived) :
     190        3200 :           base_ptr(const_cast<Base*>(static_cast<Base const *>(derived)))
     191             :       {
     192             :         static_assert( std::is_base_of<Base, Derived>::value, "Can only use virtual_base_class on a valid base class" );
     193        3200 :         base_class_detail::RegisterPolymorphicBaseClass<Base, Derived>::bind();
     194        3200 :       }
     195             : 
     196             :         Base * base_ptr;
     197             :     };
     198             : 
     199             : } // namespace cereal
     200             : 
     201             : #endif // CEREAL_TYPES_BASE_CLASS_HPP_

Generated by: LCOV version 1.11