123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- /*! \file adapters.hpp
- \brief Archive adapters that provide additional functionality
- on top of an existing archive */
- /*
- Copyright (c) 2014, Randolph Voorhies, Shane Grant
- All rights reserved.
- Redistribution and use in source and binary forms, with or without
- modification, are permitted provided that the following conditions are met:
- * Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in the
- documentation and/or other materials provided with the distribution.
- * Neither the name of the copyright holder nor the
- names of its contributors may be used to endorse or promote products
- derived from this software without specific prior written permission.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
- DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- #ifndef CEREAL_ARCHIVES_ADAPTERS_HPP_
- #define CEREAL_ARCHIVES_ADAPTERS_HPP_
- #include "cereal/details/helpers.hpp"
- #include <utility>
- namespace cereal
- {
- #ifdef CEREAL_FUTURE_EXPERIMENTAL
- // Forward declaration for friend access
- template <class U, class A> U & get_user_data( A & );
- //! Wraps an archive and gives access to user data
- /*! This adapter is useful if you require access to
- either raw pointers or references within your
- serialization functions.
- While cereal does not directly support serialization
- raw pointers or references, it is sometimes the case
- that you may want to supply something such as a raw
- pointer or global reference to some constructor.
- In this situation this adapter would likely be used
- with the construct class to allow for non-default
- constructors.
- @note This feature is experimental and may be altered or removed in a future release. See issue #46.
- @code{.cpp}
- struct MyUserData
- {
- int * myRawPointer;
- std::reference_wrapper<MyOtherType> myReference;
- };
- struct MyClass
- {
- // Note the raw pointer parameter
- MyClass( int xx, int * rawP );
- int x;
- template <class Archive>
- void serialize( Archive & ar )
- { ar( x ); }
- template <class Archive>
- static void load_and_construct( Archive & ar, cereal::construct<MyClass> & construct )
- {
- int xx;
- ar( xx );
- // note the need to use get_user_data to retrieve user data from the archive
- construct( xx, cereal::get_user_data<MyUserData>( ar ).myRawPointer );
- }
- };
- int main()
- {
- {
- MyUserData md;
- md.myRawPointer = &something;
- md.myReference = someInstanceOfType;
- std::ifstream is( "data.xml" );
- cereal::UserDataAdapter<MyUserData, cereal::XMLInputArchive> ar( md, is );
- std::unique_ptr<MyClass> sc;
- ar( sc ); // use as normal
- }
- return 0;
- }
- @endcode
- @relates get_user_data
- @tparam UserData The type to give the archive access to
- @tparam Archive The archive to wrap */
- template <class UserData, class Archive>
- class UserDataAdapter : public Archive
- {
- public:
- //! Construct the archive with some user data struct
- /*! This will forward all arguments (other than the user
- data) to the wrapped archive type. The UserDataAdapter
- can then be used identically to the wrapped archive type
- @tparam Args The arguments to pass to the constructor of
- the archive. */
- template <class ... Args>
- UserDataAdapter( UserData & ud, Args && ... args ) :
- Archive( std::forward<Args>( args )... ),
- userdata( ud )
- { }
- private:
- //! Overload the rtti function to enable dynamic_cast
- void rtti() {}
- friend UserData & get_user_data<UserData>( Archive & ar );
- UserData & userdata; //!< The actual user data
- };
- //! Retrieves user data from an archive wrapped by UserDataAdapter
- /*! This will attempt to retrieve the user data associated with
- some archive wrapped by UserDataAdapter. If this is used on
- an archive that is not wrapped, a run-time exception will occur.
- @note This feature is experimental and may be altered or removed in a future release. See issue #46.
- @note The correct use of this function cannot be enforced at compile
- time.
- @relates UserDataAdapter
- @tparam UserData The data struct contained in the archive
- @tparam Archive The archive, which should be wrapped by UserDataAdapter
- @param ar The archive
- @throws Exception if the archive this is used upon is not wrapped with
- UserDataAdapter. */
- template <class UserData, class Archive>
- UserData & get_user_data( Archive & ar )
- {
- try
- {
- return dynamic_cast<UserDataAdapter<UserData, Archive> &>( ar ).userdata;
- }
- catch( std::bad_cast const & )
- {
- throw ::cereal::Exception("Attempting to get user data from archive not wrapped in UserDataAdapter");
- }
- }
- #endif // CEREAL_FUTURE_EXPERIMENTAL
- } // namespace cereal
- #endif // CEREAL_ARCHIVES_ADAPTERS_HPP_
|