我有一个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++ << ", ";
演示。