gintenlib::new_
は、新しくオブジェクトを new
演算子を用いて生成し、そのアドレスを boost::shared_ptr
に格納して返す関数テンプレートです。
これだけならば boost::make_shared
を使うべきなのですが、gintenlib::new_
には boost::make_shared
に存在しない利点があります。アクセス制御機能です。
gintenlib::new_
関数からの new
演算子呼び出しは、常に gintenlib::new_core_access
クラスから行われます。つまり、コンストラクタを private
にした上で gintenlib::new_core_access
を friend
宣言することで、 gintenlib::new_
を使うことでしか生成することのできないクラスを作れるのです。
無論、 gintenlib::new_
を使わなくても、生成用の static
関数を作ることで、同じ機能は再現することが出来ます。
ですが、生成用の static
関数なんて、文面は決まりきったものであり、わざわざ定義するのは面倒というもの。 gintenlib::new_
を使えば、その煩雑さを取り除くことができます。
他にも、「他のオブジェクトと全く同じ表現で構築できる」というメリットもありますし、何より、
xxx::make_xxx( arglist )
と gintenlib::new_
ならば、好みにもよりますが、後者のほうが格好いいでしょう?
「でも、この方法だと、全ての private
コンストラクタを公開しちゃうじゃないか。流石にそれはちょっと・・・」と思うかもしれません。が、心配は無用です。
そういう場合は、 gintenlib::enable_static_new_
を使いましょう。使い方は、
struct hoge : gintenlib::enable_static_new_<hoge> { // 構築。 public に置いているが、 gintenlib::new_core_access を friend 宣言すれば // private に置いてもよくなる。まー普通に考えて一般公開しない手ないのですが static boost::shared_ptr<hoge> new_( /* args */ ) { return boost::shared_ptr<hoge>( new hoge( /* args */ ) ); } // なお gintenlib::new_ 的には hoge* を返してもOKですが、 // 生ポインタ返す生成関数を public に置く意味は不明。非推奨です。 // メソッドとか適当に private: // 構築を private に hoge( /* args */ ); // コピーも禁止 hoge( const hoge& ); // メインのほかに private なコンストラクタを作っても // gintenlib::new_ は static 関数の new_ を優先するので問題ない // メンバとか適当に };
以上。C++ プログラマにとっては割とおなじみの記法ですね。
こうしておくことで、一般的なオブジェクトと全く同じように、
boost::shared_ptr<int> p1 = gintenlib::new_<int>(); boost::shared_ptr<hoge> p2 = gintenlib::new_<hoge>();
って感じに記述できます。なくてもいいけどあれば少し便利でしょう?
以下はライブラリの細かい仕様ですので、読んでも読まなくても:
gintenlib::new_ 仕様
- 収録ヘッダ
<gintenlib/new_.hpp>
内- 名前空間
gintenlib
- ライブラリのリンク
- 必要なし
namespace gintenlib { // new_ の戻り値のポインタ型(現在は boost::shared_ptr 一択) template<typename T> struct ptr { typedef boost::shared_ptr<T> type; }; // このクラスから継承することで、gintenlib::new_ からは、 // コンストラクタではなく static の new_ 関数が呼ばれるようになる template<typename Derived > struct enable_static_new_ {}; // 上のクラスを継承しているかどうかを判断するクラス template<typename T> struct enable_if_enabled_static_new_ : boost::enable_if< boost::is_base_of< enable_static_new_<T>, T > > {}; // クラスの private メンバアクセス用のクラス。 // コンストラクタないし new_ 静的関数を private においた上で、 // friend class gintenlib::new_core_access; // とすれば、 new_ を介してしか製作できないクラスになる。 class new_core_access; // 関数オブジェクト版 new_(コンストラクタ版) template<typename T> struct new_ptr { typedef typename ptr<T>::type result_type; // 実際の機能。 new して ptr<T>::type でくるむ result_type operator()() const; template<typename A1> result_type operator()( const A1& arg1 ); template<typename A1, typename A2> result_type operator()( const A1& arg1, const A2& arg2 ); // 以下、引数の個数は GINTENLIB_ARG_COUNT (=10) 個まで対応 }; // 本体 template<typename T> inline typename ptr<T>::type new_(); template<typename A1> inline typename ptr<T>::type new_( const A1& arg1 ); template<typename A1, typename A2> inline typename ptr<T>::type new_( const A1& arg1, const A2& arg2 ); // これも同様に引数は GINTENLIB_ARG_COUNT (=10) 個まで対応 } // namespace gintenlib
gintenlib::ptr メタ関数
// new_ の戻り値のポインタ型(現在は boost::shared_ptr 一択) template<typename T> struct ptr { typedef boost::shared_ptr<T> type; };
- 機能
gintenlib::new_
の機能(ファンクタ、関数両方)によって作られるポインタの型を指定する。- 戻型
boost::shared_ptr<T>
。 ゆくゆくは T の型によって生成されるポインタを可変に出来るようにする可能性有り(gintenlib::reference_counter<T>
から派生された場合はboost::intrusive_ptr<T>
にする等)。 ただしその変更は、互換性の為、メジャーバージョンアップ時にのみ行うとする
enable_static_new_<T> クラステンプレート
template<typename Derived > struct enable_static_new_ {};
- 機能
- クラス T を作る際、
enable_static_new_<T>
からpublic
継承させることで、gintenlib::new_
の機能(ファンクタ、関数両方)によって呼ばれる関数を、デフォルトのnew
演算子から、T の静的関数T::new_
に変更する。 - 補足
gintenlib::new_
(ファンクタ、関数両方)は、あくまでも T 型がenable_static_new_<T>
型から派生されているときのみ、new
演算子ではなくnew_
静的関数を呼び出す。 たとえ T の基底クラスBase
がenable_static_new_<Base>
を継承していても、T のgintenlib::new_
呼び出しには、一切関係しない。
new_core_access クラス
class new_core_access;
本体
// new 演算子を呼び出して ptr<T>::type でくるむ template<typename T> inline typename ptr<T>::type new_(); template<typename A1> inline typename ptr<T>::type new_( const A1& arg1 ); template<typename A1, typename A2> inline typename ptr<T>::type new_( const A1& arg1, const A2& arg2 ); // 以下、引数は GINTENLIB_ARG_COUNT (=10) 個まで対応 // 関数オブジェクト版 template<typename T> struct new_ptr { typedef typename ptr<T>::type result_type; // new_ 関数と全く同じである result_type operator()() const; // 多引数版も同様に用意 };
備考
このライブラリの基本機能は、 boost::make_shared
と全く同様である。よって、enable_static_new_
や new_core_access
の機能を使わないのならば、 boost::make_shared
を使うべきである。