4

複数の派生クラスの基本クラスが与えられた場合、目標は、STL コンテナーが基本インターフェイスを持つオブジェクトを参照できるようにするラッパー クラスを作成することでしたが、実際にはさまざまな派生クラスがコンテナーに追加される可能性があります。(異種の std::list からデータを取得するを参照してください)。

unique_ptrいくつかいじくり回した後、基本クラスのラッパーである新しい派生クラスを思いつきました。ただし、移動コンストラクターには混乱があります。

class Base {
    friend class BaseWrapper;
    virtual Base * clone () const = 0;
public:
    virtual ~Base () {}
    //... public interface
};

class Derived : public Base {
    //... specific members for derived class
    Base * clone () const { return new Derived(*this); }
public:
    //... implement public interface
};

class BaseWrapper : public Base {
    std::unique_ptr<Base> ptr_;
    Base * clone () const { return ptr_->clone(); }
public:
    BaseWrapper (const Base &b) : ptr_(b.clone()) {}
    //... implement public interface by forwarding to ptr_
};

typedef std::list<BaseWrapper> BaseList;

int main () {
    BaseList l;
    l.push_back(Derived());
}

これは g++ 4.7.2 ではコンパイルできません

を使用するために、次BaseWrapperのような public move コンストラクターを実装できます。

    BaseWrapper (BaseWrapper &&bw) { ptr_.swap(bw.ptr_); }

そして、これはうまくいきます。しかし、プライベートにすると、コンパイルされません

ただし、上記の代わりに、プライベートな「コピー」コンストラクターを定義できることがわかりました(もちろん、パブリックにすることもできます)。

    BaseWrapper (BaseWrapper &bw) { ptr_.swap(bw.ptr_); }

これがうまくいくはずだったのか、なぜ、またはなぜうまくいかないのか、誰か教えてもらえますか? 動作するはずなのに、移動コンストラクターを非公開にできないのはなぜですか?

上記をより完全な方法で説明するおもちゃプログラムへのこのリンクをたどることができます。

4

1 に答える 1