templateとコピーコンストラクタを組み合わせたみたところ死亡(スペランカー先生のように)

諸事情で、所有権付 auto_ptr が欲しくなったので、yaneSDK 2nd の auto_ptr をベースにして

class B{};
class D : public B{};

auto_ptr<D> d(new D);
auto_ptr<B> b1(d);
auto_ptr<B> b2(b1)

見たいなのが出来るようにちょいと手を入れてみたわけです。(基底クラスのデストラクタが仮想じゃないよ! って突っ込みはさておいて^^;)

さて、このクラスを利用すると…どーにも実行時に落ちてしまう。


結論としては、コンストラクタが悪かったのですが………。とりあえず、こんな2つのコンストラクタを定義していました


template<class T> class auto_ptr {
public:
    explicit auto_ptr(T *_P = 0)
        : m_bOwner(_P != 0), m_lp(_P)
    { // ●ここに break point
    
    }

    template<typename U>
    auto_ptr(const auto_ptr<U>& _Y)
        : m_bOwner(_Y.IsOwner())
        , m_lp(_Y.get())
    { // ●ここに break point
        const_cast<auto_ptr<U>*>(&_Y)->SetOwner(false);
    }
    :

break point を仕掛けてチェックしてみた所、どうにも auto_ptr 同士をコピーする2番目の コピーコンストラクauto_ptr<const auto_ptr<T>& _Y) が呼び出されずデータメンバ値がコピーされる こと があるようで、それにより所有権の受け渡しが上手くいかないことがあるようでした。




……って、なんでやねん…! orz




調査してみると実に単純でした。どうにも2番目のコンストラクタは「コピーコンストラクタとしては機能しない!」様です。

いやまぁ、テンプレート引数 U に、T とは違う型が指定されてしまった場合「単なるコンストラクタ」になってしまいますが、UT と同じ型が指定された場合、コピーコンストラクタになるんちゃうのかと!? こんな具合に…!!

class B{};
class D : public B{};

auto_ptr<D> d;

// ↓T == class B, U == class D なので、これは単なるコンストラクタ
auto_ptr<B> b1(d);

// ↓T == class B, U == class B なので、コピーコンストラクタ…?
auto_ptr<B> b2(b1)

……えーっと、デフォルトコピーコンストラクタが利用されてました。orz


つまりは、2番目のコンストラクタの template 引数 UT は勝手に入らない。 というのが結論のようです。 デフォルトコンストラクタの方が優先順位が高いのね……。 同じ型のは、自前で再度定義しないとダメなのね…。orz



早朝にこの問題に遭遇して、不貞寝してました。ギギギ...