16

我想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_inserter并且std::back_insert_iterator也因相同的错误而失败。

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

4

9 回答 9

23

不幸的是std::queue,“适应”了已知的功能push_backpush这意味着该标准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 ) );
于 2009-11-12T16:58:22.433 回答
8

队列不允许迭代其元素。

来自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 很愚蠢。

于 2009-11-12T16:38:29.997 回答
3

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

于 2009-11-12T16:34:51.093 回答
3

我很确定它是行不通的——队列提供了push,但插入迭代器期望使用push_frontor push_back。没有真正的理由你不能自己写push_insert_iterator(或任何你喜欢的名字),但这有点痛苦......

于 2009-11-12T16:43:52.883 回答
3

insert_iterator并且back_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;
};

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

于 2009-11-12T16:55:37.323 回答
2

您需要的是一个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使用方法(例如queue, )与任何容器(或​​者容器适配器)一起使用stack

于 2009-11-12T16:40:46.870 回答
2

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);
于 2009-11-12T16:41:21.687 回答
1

对于 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); }  );
于 2019-09-05T16:33:23.087 回答
0

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

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

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

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

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

于 2009-11-12T16:48:01.897 回答