【问题标题】:iterator over references of std::vector<std::unique_ptr<T>>迭代 std::vector<std::unique_ptr<T>> 的引用
【发布时间】:2014-11-13 00:05:57
【问题描述】:

我有一个具有std::vector&lt;std::unique_ptr&lt;T&gt;&gt; 的类,我想在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的引用进行交互?

【问题讨论】:

  • 法向量迭代器有什么问题?
  • 你想做什么? vector 的迭代器类型有一个 typedef。
  • 我想最好交换声明并改用std::unique_ptr&lt;std::vector&lt;Pointer&gt; &gt;。
  • 我已将其作为重复项关闭,因为我认为您要问的是“我如何获得一个在取消引用时返回 Pointer 的迭代器,而不是unique_ptr&lt;Pointer&gt;?”如果这不是您要问的,请澄清问题并重新打开它。

标签: c++ c++14


【解决方案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) 因为它是一个指针,你必须通过-&gt;取消引用传递的元素。

【讨论】:

  • 我刚刚看到 Brian Chen 在他对原始帖子的评论中已经提供了几乎相同的内容。
【解决方案2】:

其实这个问题的解决方案已经在 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 可以在&lt;boost/iterator/indirect_iterator.hpp&gt; 中找到。
可以如下使用:

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

Demo.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-02-02
    • 2019-11-07
    • 2015-10-11
    • 2015-09-27
    • 1970-01-01
    • 1970-01-01
    • 2022-10-21
    相关资源
    最近更新 更多