1 #ifndef BOOST_SERIALIZATION_STATE_SAVER_HPP
2 #define BOOST_SERIALIZATION_STATE_SAVER_HPP
3 
4 // MS compatible compilers support #pragma once
5 #if defined(_MSC_VER)
6 # pragma once
7 #endif
8 
9 /////////1/////////2/////////3/////////4/////////5/////////6/////////7/////////8
10 // state_saver.hpp:
11 
12 // (C) Copyright 2003-4 Pavel Vozenilek and Robert Ramey - http://www.rrsd.com.
13 // Use, modification and distribution is subject to the Boost Software
14 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
15 // http://www.boost.org/LICENSE_1_0.txt)
16 
17 //  See http://www.boost.org/libs/serialization for updates, documentation, and revision history.
18 
19 // Inspired by Daryle Walker's iostate_saver concept.  This saves the original
20 // value of a variable when a state_saver is constructed and restores
21 // upon destruction.  Useful for being sure that state is restored to
22 // variables upon exit from scope.
23 
24 
25 #include <boost/config.hpp>
26 #ifndef BOOST_NO_EXCEPTIONS
27     #include <exception>
28 #endif
29 
30 #include <boost/call_traits.hpp>
31 #include <boost/noncopyable.hpp>
32 #include <boost/type_traits/has_nothrow_copy.hpp>
33 #include <boost/core/no_exceptions_support.hpp>
34 
35 #include <boost/mpl/eval_if.hpp>
36 #include <boost/mpl/identity.hpp>
37 
38 namespace boost {
39 namespace serialization {
40 
41 template<class T>
42 // T requirements:
43 //  - POD or object semantic (cannot be reference, function, ...)
44 //  - copy constructor
45 //  - operator = (no-throw one preferred)
46 class state_saver : private boost::noncopyable
47 {
48 private:
49     const T previous_value;
50     T & previous_ref;
51 
52     struct restore {
invokeboost::serialization::state_saver::restore53         static void invoke(T & previous_ref, const T & previous_value){
54             previous_ref = previous_value; // won't throw
55         }
56     };
57 
58     struct restore_with_exception {
invokeboost::serialization::state_saver::restore_with_exception59         static void invoke(T & previous_ref, const T & previous_value){
60             BOOST_TRY{
61                 previous_ref = previous_value;
62             }
63             BOOST_CATCH(::std::exception &) {
64                 // we must ignore it - we are in destructor
65             }
66             BOOST_CATCH_END
67         }
68     };
69 
70 public:
state_saver(T & object)71     state_saver(
72         T & object
73     ) :
74         previous_value(object),
75         previous_ref(object)
76     {}
77 
~state_saver()78     ~state_saver() {
79         #ifndef BOOST_NO_EXCEPTIONS
80             typedef typename mpl::eval_if<
81                 has_nothrow_copy< T >,
82                 mpl::identity<restore>,
83                 mpl::identity<restore_with_exception>
84             >::type typex;
85             typex::invoke(previous_ref, previous_value);
86         #else
87             previous_ref = previous_value;
88         #endif
89     }
90 
91 }; // state_saver<>
92 
93 } // serialization
94 } // boost
95 
96 #endif //BOOST_SERIALIZATION_STATE_SAVER_HPP
97