3

shared_ptr をゼロから実装してどのように機能するかを学ぼうとしていますが、T の基底クラスを検出する方法がわかりません。

is_base_of() を使用してみましたが、const 値が得られ、if ステートメントで使用してオブジェクトの内部の weak_ptr を設定することはできません。

私はこれらの線に沿って考えていました:

template <class T>
class shared_ptr
{
    shared_ptr(T* ptr)
    {
        ...
    }

    shared_ptr(enable_shared_from_this<T>* ptr)
    {
        ...

        Ptr->m_this = weak_ptr<T>(this);
    }
};

しかし、これまでのところ運がありません。Boost と VC++ の実装は私にはわかりにくいので、簡単な説明を探しています。

ここでそれは言います

std::shared_ptr のコンストラクターは enable_shared_from_this ベースの存在を検出し、新しく作成された std::shared_ptr を内部に格納された弱参照に割り当てます。

ええ、どうやって?

4

2 に答える 2

1

1 つのオプションは、関数テンプレートのオーバーロードに基づいて作成することです。

ここに単純化された解決策があります: 2 つのクラス A と B があります。クラス A は H から派生します。関数is_derived_from_hはオーバーロードされ、一部のクラス X が H から派生したかどうかを検出するために使用できます。

#include <stdlib.h>
#include <iostream>

class H {};
class A: public H {};
class B {};

// (1)
template <typename X>
void is_derived_from_h(X* px, H* ph) {
  std::cout << "TRUE" << std::endl;
}

// (2)
void is_derived_from_h(...) {
  std::cout << "FALSE" << std::endl;
}

int main(int argc, char* argv[]) {

  A* pa = new A;
  B* pb = new B;

  is_derived_from_h(pa, pa); // (1) is selected, the closest overload
  is_derived_from_h(pb, pb); // (2) is selected, (1) is not viable

  delete pa;
  delete pb;

  return EXIT_SUCCESS;
}

出力:

TRUE
FALSE

Boost の場合は、次の呼び出しをトレースします。

shared_ptr( Y * p )
->
boost::detail::sp_pointer_construct( this, p, pn );
  ->
boost::detail::sp_enable_shared_from_this( ppx, p, p );

にはいくつかのバージョンがありsp_enable_shared_from_thisます。Y の派生元であるかどうかに基づいて選択されるバージョンenable_shared_from_this

于 2014-10-11T22:21:06.483 に答える
1

シンプル - テンプレートの引数推定を使用してください! これが世界のすべての問題に対する解決策ですが、あなたはすでにそれを知っていました:) ブーストがあなたの問題を解決する方法に基づく解決策を以下に示します。構築の詳細を実際に処理するテンプレート化されたヘルパー クラスを作成します。

template <class T>
class shared_ptr
{
    shared_ptr(T* ptr)
    {
        magic_construct(this, ptr, ptr);
    }
};

template <class X, class Y, class Z>
void magic_construct(shared_ptr<X>* sp, Y* rp, enable_shared_from_this<Z>* shareable)
{
//Do the weak_ptr handling here
}

void magic_construct(...)//This is the default case
{
//This is the case where you have no inheritance from enable_shared_from_this
}
于 2014-10-11T22:48:34.893 に答える