--- /dev/null
+#ifndef GINTENLIB_INCLUDED_INTRUSIVE_PTR_HOOK_HPP_
+#define GINTENLIB_INCLUDED_INTRUSIVE_PTR_HOOK_HPP_
+
+/*
+
+ <gintenlib/intrusive_ptr_hook.hpp>
+
+ intrusive_ptr_hook : boost::intrusive_ptr 用オブジェクト生成(削除子指定版)
+
+ 宣言:
+ template<typename Derived, typename Deleter = deleter, typename Counter = int>
+ class intrusive_ptr_hook
+ {
+ protected:
+ // 型定義
+ typedef Counter counter_type;
+ typedef Deleter deleter;
+
+ // デフォルトコンストラクタ
+ intrusive_ptr_hook();
+ // コピーコンストラクタ(コピーしない)
+ intrusive_ptr_hook( this_type const& );
+ // 削除子指定
+ explicit intrusive_ptr_hook( Deleter const& d );
+ // 初期カウント指定
+ explicit intrusive_ptr_hook( counter_type initial_count );
+ // 初期カウント指定&削除子指定
+ intrusive_ptr_hook( counter_type initial_count, Deleter const& d );
+
+ // operator=(何もしない)
+ this_type& operator=( const this_type& );
+
+ // メンバアクセス
+ counter_type use_count() const;
+ deleter& get_deleter();
+ deleter const& get_deleter() const;
+
+ // ADLによって呼び出される参照カウントアクセス関数群
+ // カウントの増減
+ friend void intrusive_ptr_add_ref( Derived const* p );
+ friend void intrusive_ptr_release( Derived const* p );
+ // カウントチェック(独自拡張)
+ friend void intrusive_ptr_use_count( Derived const* p );
+
+ };
+
+ template< typename T, bool b >
+ inline void intrusive_ptr_add_ref( const reference_counter<T, b>* ptr );
+ template< typename T, bool b >
+ inline void intrusive_ptr_release( const reference_counter<T, b>* ptr );
+
+ 使用法:
+ class hoge
+ : public gintenlib::intrusive_ptr_hook<hoge>
+ {
+ // 実装
+ };
+
+ 仕様:
+ ・ADL
+ intrusive_ptr_add_ref, intrusive_ptr_release, intrusive_ptr_use_count は
+ ADLによってのみ呼び出されます。gintenlib::intrusive_ptr_xxx とは呼べません。
+ intrusive_ptr_hook を継承することが原因で、継承先のクラスのADL対象に
+ gintenlib 名前空間が加わることはありません。
+ ・例外仕様
+ Deleter のコピーコンストラクタにおいて例外が投げられない限り、例外安全です。
+ ・マルチスレッド対応
+ カウンタによって対処します(現在検討中)。
+ ・コピー関連の動作
+ コピー、代入操作は、一貫して「何も行わない」方針を採っています。
+ コピー初期化される場合は、カウンタ、削除子、共にデフォルト値で初期化されます。
+ 代入される場合は、カウンタ、削除子、共にまったく影響を受けません。
+
+*/
+
+#include "deleter.hpp"
+
+#include <cassert>
+#include <boost/compressed_pair.hpp>
+
+namespace gintenlib
+{
+ namespace intrusive_ptr_hook_ // ADL 回避用
+ {
+ template<typename Derived, typename Deleter = deleter, typename Counter = int>
+ class intrusive_ptr_hook
+ {
+ typedef intrusive_ptr_hook this_type;
+
+ protected:
+ // 型定義
+ typedef Counter counter_type;
+ typedef Deleter deleter;
+
+
+ // デフォルトコンストラクタ
+ intrusive_ptr_hook()
+ : pair_( counter_type(), deleter() ) {}
+ // コピーコンストラクタ(コピーしない)
+ intrusive_ptr_hook( this_type const& )
+ : pair_( counter_type(), deleter() ) {}
+ // 削除子指定
+ explicit intrusive_ptr_hook( Deleter const& d )
+ : pair_( counter_type(), d ) {}
+ // 初期カウント指定
+ explicit intrusive_ptr_hook( counter_type initial_count )
+ : pair_( initial_count, deleter() ) {}
+ // 初期カウント指定&削除子指定
+ intrusive_ptr_hook( counter_type initial_count, Deleter const& d )
+ : pair_( initial_count, d ) {}
+
+ // operator=(何もしない)
+ this_type& operator=( const this_type& )
+ {
+ return *this;
+ }
+
+ // メンバアクセス
+ counter_type use_count() const { return count_(); }
+
+ deleter& get_deleter() { return deleter_(); }
+ deleter const& get_deleter() const { return deleter_(); }
+
+
+ private:
+ // メンバ
+ typedef boost::compressed_pair<counter_type, deleter> pair_type;
+ mutable pair_type pair_;
+
+ counter_type& count_() const { return pair_.first(); }
+ deleter& deleter_() const { return pair_.second(); }
+
+ // Derived からのメンバアクセス
+ static counter_type& get_count( Derived const& x )
+ {
+ return static_cast<this_type const&>(x).count_();
+ }
+ static deleter const& get_deleter( Derived const& x )
+ {
+ return static_cast<this_type const&>(x).get_deleter();
+ }
+
+
+ // カウントの増減
+ // ADLによって呼び出される
+ friend void intrusive_ptr_add_ref( Derived const* p )
+ {
+ using namespace std;
+ assert( p != 0 );
+
+ counter_type& count = get_count(*p);
+ assert( count >= 0 );
+
+ ++count;
+
+ }
+ friend void intrusive_ptr_release( Derived const* p )
+ {
+ using namespace std;
+ assert( p != 0 );
+
+ counter_type& count = get_count(*p);
+ assert( count > 0 );
+
+ --count;
+
+ if( count == 0 )
+ {
+ // p の破棄処理の途中で deleter が削除されると困るのでコピーする
+ deleter d = get_deleter(*p);
+ // 削除本体
+ d(p);
+ }
+ }
+ // カウントチェック(独自拡張)
+ friend counter_type intrusive_ptr_use_count( Derived const* p )
+ {
+ using namespace std;
+ assert( p != 0 );
+
+ counter_type const count = get_count(*p);
+ assert( count >= 0 );
+
+ return count;
+ }
+
+
+ }; // intrusive_ptr_hook<Derived, Deleter>
+
+ } // namespace intrusive_ptr_hook_
+ using namespace intrusive_ptr_hook_;
+
+} // namespace gintenlib
+
+
+#endif // #ifndef GINTENLIB_INCLUDED_INTRUSIVE_PTR_HOOK_HPP_
--- /dev/null
+// ヘッダ
+#include "../gintenlib/intrusive_ptr_hook.hpp"
+
+// boost の単体テストフレームワーク
+#include <boost/test/minimal.hpp>
+
+// これがないとテストしようがない
+#include <boost/intrusive_ptr.hpp>
+
+// 通常版
+struct simple
+ : gintenlib::intrusive_ptr_hook<simple>
+{
+ static int instances;
+
+ simple() { ++instances; }
+ ~simple() throw () { --instances; }
+
+ int use_count() const
+ {
+ return intrusive_ptr_use_count( this );
+ }
+
+};
+int simple::instances = 0;
+
+void simple_test()
+{
+ BOOST_CHECK( simple::instances == 0 );
+ {
+ // 通常の生成と破棄
+ simple const x;
+ BOOST_CHECK( simple::instances == 1 );
+ BOOST_CHECK( x.use_count() == 0 );
+ }
+ BOOST_CHECK( simple::instances == 0 );
+ {
+ // 本番
+ boost::intrusive_ptr<simple const> p1( new simple ), p2( new simple );
+ BOOST_CHECK( simple::instances == 2 );
+ BOOST_CHECK( p1->use_count() == 1 );
+ BOOST_CHECK( p2->use_count() == 1 );
+ // 移動させてカウントを変化させる
+ p2 = p1;
+ BOOST_CHECK( simple::instances == 1 );
+ BOOST_CHECK( p1->use_count() == 2 );
+ BOOST_CHECK( p2->use_count() == 2 );
+ }
+ BOOST_CHECK( simple::instances == 0 );
+}
+
+int test_main( int, char** )
+{
+ simple_test();
+
+ return 0;
+}
+