OSDN Git Service

memberwise_swap を追加
[gintenlib/gintenlib.git] / gintenlib / typed_saver.hpp
1 #ifndef GINTENLIB_INCLUDED_TYPED_SAVER_HPP_
2 #define GINTENLIB_INCLUDED_TYPED_SAVER_HPP_
3
4 /*
5
6       <gintenlib/typed_saver.hpp>
7
8   typed_saver : デストラクタでの値の復帰(テンプレート版)
9
10   宣言:
11     template< typename T >
12     class typed_saver : boost::noncopyable
13     {
14      public:
15       // 普通のコンストラクタ
16       explicit typed_saver( T& t );
17       // t の値を退避してから t1 に書き換える
18       typed_saver( T& t, const T& t1 );
19       
20       ~typed_saver();
21       
22       // これを呼ぶと、デストラクタで値が戻されることはなくなる
23       void release();
24       
25       // 明示的な復帰(通常はデストラクタで復帰されるので書く必要なし)
26       void restore();
27       
28     };
29     
30   機能:
31     コンストラクタで受け取った変数の値を記録し、デストラクタで書き戻します。
32     value_saver と違い変数の型を指定する必要がありますが、その分高速に動作します。
33     
34     デストラクタ前でも restore() 関数を呼び出せば、強制的に書き戻すことが可能です。
35     その時はデストラクタでの値の書き戻しは行われませんので注意してください。
36     またデストラクタでの書き戻しを抑制したいときは、 release() 関数を呼び出せば OK です。
37   
38   補足事項:
39     typed_saver, value_saver を利用できるオブジェクトの条件は、
40     「コピーコンストラクタか所有権移動コンストラクタを持っている」「 swap 可能」の二点です。
41     なので、ちゃんとした swap さえ実装すれば std::auto_ptr 等の変則クラスでも利用できます。
42
43 */
44
45 #include <algorithm>
46
47 #include <boost/noncopyable.hpp>
48 #include <boost/utility/addressof.hpp>
49
50 namespace gintenlib
51 {
52   // コンストラクタの時の値に、デストラクタで強制復帰させるオブジェクト
53   template< typename T >
54   class typed_saver
55     : boost::noncopyable
56   {
57    public:
58     // t の値を記録し、デストラクタで巻き戻す
59     explicit typed_saver( T& t )
60       : target_( boost::addressof(t) ), saver_(t) {}
61     
62     // t の値を記録してから、t1 に変更、デストラクタで戻す
63     typed_saver( T& t, const T& t1 )
64       : target_( boost::addressof(t) ), saver_(t)
65     {
66       t = t1;
67     }
68     
69     
70     // 復帰
71     ~typed_saver()
72     {
73       restore();
74     }
75     
76     // 復帰処理の抑制
77     void release()
78     {
79       target_ = 0;
80     }
81     
82     // 明示的な復帰(通常はデストラクタで復帰されるので書く必要なし)
83     void restore()
84     {
85       if( target_ )
86       {
87         using std::swap;
88         swap( *target_, saver_ );
89         target_ = 0;
90       }
91     }
92
93    private:
94     T* target_;
95     T saver_;
96
97   };  // class typed_saver<T>
98
99 }   // namespace gintenlib
100
101 #endif  // #ifndef GINTENLIB_INCLUDED_TYPED_SAVER_HPP_