繁体   English   中英

使用 std::copy 插入 STL 队列

[英]Insert into an STL queue using std::copy

我想使用std::copy将元素插入到这样的队列中:

vector<int> v;
v.push_back( 1 );
v.push_back( 2 );

queue<int> q;

copy( v.begin(), v.end(), insert_iterator< queue<int> >( q, q.front() ) );

但这无法编译,抱怨begin不是std::queue的成员。

注意:我也用std::inserter尝试过 - 这也失败了,这次说“reference”不是“std::queue”的成员。 std::back_inserterstd::back_insert_iterator也因相同的错误而失败。

我是否遗漏了一些明显的东西,或者insert_iterator只是不适用于队列?

不幸的是, std::queue将称为push_back的函数“改编”为只是push ,这意味着标准back_insert_iterator不起作用。

可能最简单的方法(尽管在概念上很难看)是用一个寿命短的容器适配器适配器[原文如此](呃!)来适应容器适配器,该适配器与后插入迭代器的寿命一样长。

template<class T>
class QueueAdapter
{
public:
    QueueAdapter(std::queue<T>& q) : _q(q) {}
    void push_back(const T& t) { _q.push(t); }

private:
    std::queue<T>& _q;
};

像这样使用:

std::queue<int> qi;

QueueAdapter< std::queue<int> > qiqa( qi );

std::copy( v.begin(), v.end(), std::back_inserter( qiqa ) );

队列不允许迭代其元素。

来自SGI STL 文档

队列是提供容器功能的受限子集的适配器。队列是“先进先出”(FIFO) 数据结构。 1即元素被添加到队列的后面,可能会从前面移除; Q.front() 是最近加入队列的元素。 队列不允许迭代其元素。 [2]

可以完成这项工作,但不能使用insert_iterator 您必须编写类似queue_inserter来呈现迭代器接口。

更新我无法自拔并决定尝试实现您需要的迭代器。 结果如下:

template< typename T, typename U >
class queue_inserter {
    queue<T, U> &qu;  
public:
    queue_inserter(queue<T,U> &q) : qu(q) { }
    queue_inserter<T,U> operator ++ (int) { return *this; }
    queue_inserter<T,U> operator * () { return *this; }
    void operator = (const T &val) { qu.push(val); }
};

template< typename T, typename U >
queue_inserter<T,U> make_queue_inserter(queue<T,U> &q) {
    return queue_inserter<T,U>(q);
}    

这适用于这样的功能:

template<typename II, typename OI>
void mycopy(II b, II e, OI oi) {
    while (b != e) { *oi++ = *b++; }
}

但它不适用于 STL 副本,因为 STL 是愚蠢的。

std::queue不是 STL 意义上的容器,它是一个功能非常有限的容器适配器 对于您似乎需要std::vectorstd::deque (“双端队列,这是一个“真正的容器”),似乎是正确的选择。

我很确定它不会工作——队列提供push ,但插入迭代器期望使用push_frontpush_back 您没有真正的理由不能编写自己的push_insert_iterator (或您喜欢的任何名称),但这有点痛苦......

insert_iteratorback_insert_iterator仅适用于(分别)具有insertpush_back方法的容器(或适配器)—— queue没有这些。 您可以根据这些编写自己的迭代器,如下所示:

template <typename Container> 
class push_iterator : public iterator<output_iterator_tag,void,void,void,void>
{
public:
    explicit push_iterator(Container &c) : container(c) {}

    push_iterator &operator*() {return *this;}
    push_iterator &operator++() {return *this;}
    push_iterator &operator++(int) {return *this;}

    push_iterator &operator=(typename Container::const_reference value)
    {
         container.push(value);
         return *this;
    }
private:
    Container &container;
};

除非这样的东西已经存在,但我很确定它不存在。

您需要的是一个push_inserter (即执行push es 到队列中的插入器)。 据我所知,STL 中没有这样的迭代器。 我通常做的是遗憾地回到旧的 for 循环。

如果你有勇气,你可以推出自己的迭代器,大致如下:

template <typename Container>
class push_insert_iterator
{
  public:
    typedef Container                      container_type;
    typedef typename Container::value_type value_type;

    explicit push_insert_iterator(container_type & c)
        : container(c)
    {}    // construct with container

    push_insert_iterator<container_type> & operator=(const value_type & v)
    {
        //push value into the queue
        container.push(v);
        return (*this);
    }

    push_insert_iterator<container_type> & operator*()
    {
        return (*this);
    }

    push_insert_iterator<container_type> & operator++()
    {
        // Do nothing
        return (*this);
    }

    push_insert_iterator<container_type> operator++(int)
    {
        // Do nothing
        return (*this);
    }

  protected:
    container_type & container;    // reference to container
};

template <typename Container>
inline push_insert_iterator<Container> push_inserter(Container & c)
{
    return push_insert_iterator<Container>(c);
}

这只是一个草稿,但你明白了。 使用push方法(例如queuestack )与任何容器(或​​容器适配器)一起使用。

std::queue不是 STL 中的基本容器之一。 它是一个容器适配器,它使用基本 STL 容器之一(在这种情况下是std::vector std::dequestd::list顺序容器之一)构建。 它专为 FIFO 行为而设计,不会在您希望insert_iterator工作的给定迭代器上提供随机插入。 因此不可能像这样使用队列。

我能想到的最简单的方法是:

class PushFunctor
{
public:
    PushFunctor(std::queue<int>& q) : myQ(q)
    {
    }
    void operator()(int n)
    {
        myQ.push(n);
    }

private:
    std::queue<int>& myQ;
};

并像这样使用它:

queue<int> q;
PushFunctor p(q);
std::for_each(v.begin(), v.end(), p);

在这个简单的例子中,你可以写:

vector<int> v;
v.push_back( 1 );
v.push_back( 2 );

queue<int, vector<int> > q(v);

这将制作vector的副本并将其用作queue的底层容器。

当然,如果您需要在队列构建后将内容入队,这种方法将不起作用。

对于 C++11

std::for_each( v.begin(), v.end(), [&q1](int data) {  q1.push(data); }  );

和 C++14

std::for_each( v.begin(), v.end(), [&q1](auto data) {  q1.push(data); }  );

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM