2016-09-28 11 views
3

unique_ptrのベクトル、継承?このコードと仮定

class Parent {} 
class Child : public Parent {} 

static std::vector<std::unique_ptr<Child>> Foo(); 

は、この関数を記述するための簡単な方法があります:

std::vector<std::unique_ptr<Parent>> Bar() { 
    auto children = Foo(); 

    std::vector<std::unique_ptr<Parent>> parents; 
    result.insert(result.end(), std::make_move_iterator(children.begin()), 
       std::make_move_iterator(children.end())); 
    return parents; 
} 

これは動作しません:

std::vector<std::unique_ptr<Parent>> Bar() { 
    return Foo(); // Compiler error: cannot convert from vector<...> to vector<...> 
} 
+2

:これはまったく同じです生ポインタの場合の問題 – rubenvb

+0

@rubenvb:そうです、気づいたことはありません: –

答えて

4

種類が異なっています。 Foo()std::vector<std::unique_ptr<Child>>を返し、Bar()std::vector<std::unique_ptr<Parent>>を返します。それを回避する方法はありません。しかし、ではなく:

あなたが行うことができます
std::vector<std::unique_ptr<Parent>> Bar() { 
    auto children = Foo(); 

    std::vector<std::unique_ptr<Parent>> parents; 
    result.insert(result.end(), std::make_move_iterator(children.begin()), 
       std::make_move_iterator(children.end())); 
    return parents; 
} 

templace<class Cin> 
struct move_from_c{ 
    Cin* c; 
    template<class Cout> 
    operator Cout()&&{ 
    using std::begin; using std::end; 
    return {std::make_move_iterator(begin(*c)), std::make_move_iterator(end(*c))}; 
    } 
}; 
template<class C, class dC=std::remove_reference_t<C>> 
move_from_c<dC> move_from(C&&c){ 
    return {std::addressof(c)}; 
} 

をそしてあなたの関数は次のとおりです:

std::vector<std::unique_ptr<Parent>> Bar() { 
    auto tmp = Foo(); 
    return {std::make_move_iterator(tmp.begin()), std::make_move_iterator(tmp.end()));} 
} 
3

まあ、我々は他の場所で定型書くことができます

std::vector<std::unique_ptr<Parent>> Bar() { 
    return move_from(Foo()); 
} 

これにより、実装の詳細がビジネスロジックBar。 (移動がどのように行われたかは、移動の決定から分けられます)。

1

ハンドル/ボディイディオムを使用し、ハンドルクラスの実装の詳細として多態性を実装することをお勧めします。

これはあなたが意味論(コンテナで作品を)の値与え、また、あなたが簡単に関係演算子を実装することができます:

#include <vector> 
#include <memory> 

class ParentImpl { 
public: 
    virtual ~ParentImpl() = default; 
    virtual void foo() {} 
}; 
class ChildImpl : public ParentImpl {}; 

class ParentHandle 
{ 
public: 
    using ptr_type = std::unique_ptr<ParentImpl>; 

    // construct from ptr_type 
    ParentHandle(ptr_type ptr = nullptr) : ptr_(std::move(ptr_)) {} 

    // public interface defers to polymorphic implementation 
    void foo() 
    { 
    ptr_->foo(); 
    } 

private: 
    std::unique_ptr<ParentImpl> ptr_; 
}; 

static std::vector<ParentHandle> Foo() 
{ 
    std::vector<ParentHandle> result; 

    result.emplace_back(std::make_unique<ParentImpl>()); 
    result.emplace_back(std::make_unique<ChildImpl>()); 

    return result; 
} 
2

いくつかの「単純」な方法:FYI

#include <algorithm> 
#include <iterator> 

std::vector<std::unique_ptr<Base>> f1(std::vector<std::unique_ptr<Derived>> v) 
{ 
    std::vector<std::unique_ptr<Base>> result; 
    result.reserve(v.size()); 
    std::move(v.begin(), v.end(), std::back_inserter(result)); 
    return result; 
} 

std::vector<std::unique_ptr<Base>> f2(std::vector<std::unique_ptr<Derived>> v) 
{ 
    return {std::make_move_iterator(v.begin()), std::make_move_iterator(v.end())}; 
} 
+0

[Demo](http://ideone.com/dzxLLB) –