迭代器引用 std::vector<std::unique_ptr<T>>



我有一个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的引用?

需要对代码进行一些更改。

#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) 由于它是一个指针,你必须通过 -> 取消引用传递的元素。

实际上,这个问题的解决方案已经在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++ << ", ";

演示

最新更新