对std :: vector <std :: unique_ptr <t>&gt; </std :: unique_ptr <t>的引用的迭代器

时间:2014-11-13 00:05:57

标签: c++ c++14

我有一个具有std::vector<std::unique_ptr<T>>的类,我想在std::unique_ptr持有的指针引用上创建一个迭代器。

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

class Pointer
{
public:
    Pointer() {}
    ~Pointer() {}

    void printSomething()
    {
        std::cout << "Hi" << std::endl;
    }
};

class Keeper
{
public:
    typedef std::vector<std::unique_ptr<Pointer>> vector_type;

    Keeper() {}
    virtual ~Keeper() {}

    void push_back(vector_type::value_type pointer)
    {
        data.push_back(pointer);
    }

    vector_type::const_iterator begin() const
    {
        return data.begin();
    }

    vector_type::const_iterator end() const
    {
        return data.end();
    }
private:
    vector_type data;
};

int main()
{
    Keeper keeper;
    keeper.push_back(std::make_unique<Pointer>());

    std::for_each(keeper.begin(), keeper.end(), [] (auto pointer) {
        pointer.printSomething();
    });
}

我遇到了一连串错误,我无法放在这里......

如何提供通过std::unique_ptr的参考进行交互的界面?

2 个答案:

答案 0 :(得分:1)

您的代码需要进行一些更改。

#include<type_traits>

class Keeper
{
//...
public:
    void push_back(value_type&& pointer)
    {
        data.push_back(std::move(pointer));                                  //(1)
    }
//...    
};

int main()
{
    // ...

    std::for_each(keeper.begin(), keeper.end(), [] (auto const& pointer) {   //(2)
        pointer->printSomething();                                           //(3)
    });
}


(1)unique_ptr通过右值引用并将move传递到向量中。这是必要的,因为您无法复制unique_ptr,但只应用移动。或者更好,您可以使用emplace_back并简单地传递构造函数参数

template<typename ... Args>
void emplace_back(Args&& ... args)
{
    data.emplace_back(std::forward<Args>(args) ...);
}

请注意,之前的调用等同于以下内容,因为编译器进行了隐式转换:

data.emplace_back(std::unique_ptr<Pointer>(std::forward<Args>(args) ...));


(2)通过引用传递向量的元素。同样,这是必要的,因为您无法通过值传递它们,这意味着副本。


(3)由于它是一个指针,您必须通过->取消引用传递的元素。

答案 1 :(得分:0)

实际上,此问题的解决方案已在Boost.Iterator中实现。它很性感:

std::vector<std::unique_ptr<int>> vec;
// [..]

using iterator = boost::indirect_iterator<decltype(vec)::iterator>;
iterator iter = vec.begin(),
         end = vec.end();

indirect_iterator可以在<boost/iterator/indirect_iterator.hpp>中找到 可以使用如下:

while (iter != end)
    std::cout << *iter++ << ", ";

Demo