スマートポインターラッパー(ブーストshared_ptrまたはscoped_ptrまたは別のスマートポインターラッパーを含む)を作成しようとしています。各ラッパータイプは、少し余分な機能(たとえば、ログの使用、遅延初期化、正しいコンストラクター/破棄順序の検証など)を注入しますが、ユーザーにはできるだけ見えないようにします(ラッパーをスワップイン/アウトできるようにします)。単一のtypedefを変更するだけで、場合によってはコンストラクターコードを変更するだけですが、使用法コードは変更しません)。
通常の使用法は簡単です。
template<typename T>
class some_smart_ptr_wrapper
{
public:
typedef typename T::value_type value_type;
...
value_type* get() { /*do something magic*/ return m_ptr.get(); }
const value_type* get() const { /*do something magic*/ return m_ptr.get(); }
// repeat for operator->, operator*, and other desired methods
private:
T m_ptr;
};
typedef some_smart_ptr_wrapper< boost::shared_ptr<int> > smart_int;
smart_int p;
(これで、他のすべてのコードはp
、少なくとも定義された操作では、shared_ptrと区別なく使用でき、typedefを変更するだけでラッパーを追加できます。)
複数のラッパーは、期待どおりにネストするだけで同時に使用でき、変数を宣言する(場合によっては初期化する)コードのみを処理する必要があります。
ラッパーから「基本的な」shared/scoped_ptrを取得できると便利な場合もあります(特に、ラッパーによって追加された機能をトリガーする必要のない関数への引数としてshared_ptrを渡す場合)。単一のラッパーレイヤーの場合、それは簡単です。
T& getPtr() { return m_ptr; }
const T& getPtr() const { return m_ptr; }
ただし、これは複数のラッパーレイヤーに適切にスケーリングされません(呼び出し元はp.getPtr().getPtr().getPtr()
正しい回数を実行する必要があります)。
私ができるようにしたいのは、次のようにgetPtr()を宣言することです。
- TがgetPtr()を実装している場合、m_ptr.getPtr()(どのタイプでも)を返します。
- TがgetPtr()を実装していない場合は、m_ptrを返します。
- ご想像のとおり、constフレーバーとnon-constフレーバーの両方で引き続き使用できます。
その結果、外部コードからgetPtr()を1回呼び出すだけで、元のスマートポインターへのチェーンが「ウォークアップ」されます。これは、getPtr()を実装しないのはそれだけだからです。
ソリューションにはSFINAEとboost::enable_ifが含まれると確信しています。私はそのようなものを機能させるために少し遊びましたが、これまでのところあまり運がありませんでした。
ソリューションまたは完全に代替のアプローチの両方を歓迎します。VC ++ 2008とGCCの両方で動作させたいことに注意してください(つまり、残念ながらC ++ 11はありません)。