2016-09-28 46 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) –