2016-09-28 77 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

FYI:這是完全一樣的問題與生指針一樣。 – 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; 
} 

你可以這樣做:

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

嗯,我們可以套用在其他地方寫:

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() { 
    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

一些「簡單」的方法:

#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) –