3

Herb Sutter の C++ ガイドラインに従おうとしています。この場合は、unique_ptr生のポインターとshared_ptr. を支持する議論の 1 つは、ある時点で必要になった場合のstd::unique_ptr変換可能性です。shared_ptr

私の場合、vectorofunique_ptrを取るメソッドに渡す必要があるvectorof がありshared_ptrます。私は次のようなものを書くことができることを望んでいました:

for (auto &uniquePtr : vectorUnique)
    vectorShared.push_back(make_shared<Abstract>(move(uniquePtr));

これにより、Xcode 7.1ベースのツールチェーンが構成されていると、次のエラーが発生しC++11ます。

エラー: フィールド タイプ 'Abstract' は抽象クラスです。

Abstractを使用すると、STL が型の具体的なインスタンスを保持しようとしているようmake_sharedです。そのため、多くの場合、Sutter 氏のアドバイスは役に立たないように思われるので、何か間違ったことをしているに違いないと確信しています。私は書くことに頼りました:

for (auto &uniquePtr : vectorUnique) {
    auto ptr = uniquePtr.get();
    auto shared = shared_ptr<Abstract>(ptr);
    vectorShared.push_back(shared);
    uniquePtr.release();
}

これを行うより良い方法はありますか?

4

2 に答える 2

8

make_shared指定された引数を使用して新しいオブジェクトを構築し、それに ashared_ptrを返します。したがって、コンパイラはコンストラクターを期待してAbstract(std::unique_ptr<Abstract>)いますが、これはおそらくあなたが持っているものではありません。

必要なのは、引数shared_ptrを取るコンストラクターです。unique_ptr

    vectorShared.push_back(shared_ptr<Abstract>(move(uniquePtr)));

そして、そうではないexplicitので、

    vectorShared.emplace_back(move(uniquePtr));

うまくいきます(emplace_backRichard Hodgesの提案で、冗長なコピーを避けるために使用していました)。for標準アルゴリズムもあるので、ループは必要ありません。

    std::move(vectorUnique.begin(), vectorUnique.end(),
              std::back_inserter(vectorShared));

これが定期的に必要な場合は、関数を定義できます。

#include <vector>
#include <memory>
#include <algorithm>

template<typename T>
std::vector<std::shared_ptr<T>>
        convert_to_shared(std::vector<std::unique_ptr<T>>&& vu)
{
    using std::begin;
    using std::end;
    std::vector<std::shared_ptr<T>> vs;
    vs.reserve(vu.size());
    std::move(begin(vu), end(vu), std::back_inserter(vs));
    return vs;
}


// Example of use
class Abstract {};
int main()
{
    std::vector<std::unique_ptr<Abstract>> vectorUnique;
    std::vector<std::shared_ptr<Abstract>> vectorShared
        = convert_to_shared(std::move(vectorUnique));
}

ひどい名前で申し訳ありません(提案は受け付けています)。への呼び出しを省略するとreserve()、より多くのコンテナーに一般化できます。

于 2015-12-08T18:28:50.757 に答える
2

私は次のようにします:

for (auto &uniquePtr : vectorUnique) {
    vectorShared.emplace_back(std::move(uniquePtr));
}
于 2015-12-08T18:31:20.787 に答える