1 #ifndef GINTENLIB_INCLUDED_POINTER_FACADE_HPP_
2 #define GINTENLIB_INCLUDED_POINTER_FACADE_HPP_
6 <gintenlib/pointer_facade.hpp>
8 pointer_facade : 簡易スマートポインタ製作
11 template< class Derived, typename T, typename Category = Derived >
14 typedef T element_type;
20 reference operator*() const;
21 pointer operator->() const;
22 friend pointer get_pointer( const Derived& target );
25 operator unspecified_bool_type() const;
26 bool operator!() const;
32 template<typename T, typename U, typename D1, typename D2, typename C>
33 inline bool operator==
34 ( const pointer_facade<D1, T, C>& lhs, const pointer_facade<D2, U, C>& rhs );
36 template<typename T, typename U, typename D1, typename D2, typename C>
37 inline bool operator!=
38 ( const pointer_facade<D1, T, C>& lhs, const pointer_facade<D2, U, C>& rhs );
40 template<typename T, typename U, typename D1, typename D2, typename C>
42 ( const pointer_facade<D1, T, C>& lhs, const pointer_facade<D2, U, C>& rhs );
45 get() さえ実装すれば、それを元にスマートポインタとして必要なものを生成するクラスです。
47 ・element_type, value_type, pointer, reference の型定義
48 ・operator*, operator->, get_pointer() によるポインタ取得
49 ・bool値との比較、スマートポインタ同士の比較
50 ・異なる型を示すスマートポインタ同士の比較(同じカテゴリに属するもののみ)
52 使い方は bool_comparable と同じ、「テンプレートに自分自身の型名を入れて継承」。
53 第二引数はポインタを格納するオブジェクトの型を示します。
54 省略可能な第三引数はポインタのカテゴリ、第三引数が同じスマートポインタ同士は相互比較できます。
55 省略した場合、他のスマートポインタとは比較が出来ません(でも通常は比較できた方が良いですよ?)。
56 さらに詳しくは、下の欄や、銀天ライブラリで定義されたスマートポインタの実装をご覧ください。
61 // スマートポインタを作る場合、まずカテゴリクラスを定義する。
62 // 同じ種類のスマートポインタで、同じカテゴリを共有することで、
63 // スマートポインタ同士の相互比較が(同じ種類のスマートポインタに限り)可能になる。
64 struct trivial_ptr_category {}; // カテゴリクラスはタグなので適当に
69 public gintenlib::pointer_facade< trivial_ptr<T>, T, trivial_ptr_category > // こう使う
72 trivial_ptr() : p(0) {}
73 explicit trivial_ptr( T* ptr ) : p( ptr ) {}
76 // ~trivial_ptr() throw () {}
79 T* get() const { return p; }
81 // reset とか swap もあると良いけど、基本はこれで終了!
90 trivial_ptr<int> p1( new int() );
96 cout << *p1 << endl; // OK
99 trivial_ptr<vector<int> > p2( new vector<int>() );
100 cout << p2->size() << endl; // OK
102 trivial_ptr<void> p0; // void へのポインタも適切に振り分けてくれる
103 assert( p0 != p1 ); // もちろん比較できる
109 ポインタに必要な機能はあらかた用意してくれる便利クラスですが、
110 static_pointer_cast やら swap やら reset やらは定義してくれません。忘れないように。
111 なお、 friend 関数の get_pointer や operator== なんかは、gintenlib 名前空間内に定義されます。
112 通常は ADL によって意識する必要はありませんが、古いコンパイラでは引っかかるかも。
116 #include "bool_comparable.hpp"
119 #include <functional> // for std::less
120 #include <boost/type_traits/add_reference.hpp>
124 template< typename Derived, typename T, typename Category = Derived >
125 struct pointer_facade
126 : bool_comparable< pointer_facade< Derived, T, Category > >
128 // スマートポインタとして必要なあれこれ
129 typedef T element_type;
130 typedef T value_type;
132 // reference は void 型への対応のため特殊
133 typedef typename boost::add_reference<T>::type reference;
136 reference operator*() const
139 assert( get_() != 0 );
142 pointer operator->() const
145 assert( get_() != 0 );
149 friend pointer get_pointer( const Derived& target )
155 bool operator!() const
159 // operator safe_bool は bool_comparable の管轄
164 // 派生クラスの get() を呼び出す
167 return static_cast<const Derived*>(this)->get();
174 }; // pointer_facade<Derived, T, Category>
178 template<typename T, typename U, typename D1, typename D2, typename C>
179 inline bool operator==( const pointer_facade<D1, T, C>& lhs, const pointer_facade<D2, U, C>& rhs )
181 return static_cast<const D1&>(lhs).get() == static_cast<const D2&>(rhs).get();
183 template<typename T, typename U, typename D1, typename D2, typename C>
184 inline bool operator!=( const pointer_facade<D1, T, C>& lhs, const pointer_facade<D2, U, C>& rhs )
186 return static_cast<const D1&>(lhs).get() != static_cast<const D2&>(rhs).get();
189 // < は、ポインタ型が同じ場合とそうでない場合で分ける
190 template<typename T, typename D, typename C>
191 inline bool operator< ( const pointer_facade<D, T, C>& lhs, const pointer_facade<D, T, C>& rhs )
193 // 同じポインタの比較は std::less で比較する
194 return std::less<T*>()( static_cast<const D&>(lhs).get(), static_cast<const D&>(rhs).get() );
196 template<typename T, typename U, typename D1, typename D2, typename C>
197 inline bool operator< ( const pointer_facade<D1, T, C>& lhs, const pointer_facade<D2, U, C>& rhs )
199 // 異なるポインタ同士の比較は、仕方ないので < で比較する
200 return static_cast<const D1&>(lhs).get() < static_cast<const D2&>(rhs).get();
203 } // namespace gintenlib
206 #endif // #ifndef GINTENLIB_INCLUDED_POINTER_FACADE_HPP_