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-これも失敗しました。今回は「参照」は「std::queue」のメンバーではないと言っています。 std::back_inserterまたstd::back_insert_iterator、同じエラーで失敗します。

明らかな何かが欠けているのでしょうか、それともinsert_iterator単にキューで機能しないのでしょうか?

4

9 に答える 9

23

残念ながら、標準が機能しないことを意味するだけでstd::queue知られている機能を「適応」させます。push_backpushback_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

Queue は、その要素の繰り返しを許可しません。

SGI STL ドキュメントから:

キューは、コンテナ機能の制限されたサブセットを提供するアダプタです。キューは、「先入れ先出し」(FIFO) データ構造です。1 つまり、要素はキューの後ろに追加され、前から削除される場合があります。Q.front() は、最後にキューに追加された要素です。Queue は、その要素の繰り返しを許可しません。[2]

これを機能させることはできますが、使用することはできませんinsert_iteratorqueue_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::vectorまたはstd::deque(「実際のコンテナ」である「両端キュー」)のいずれかが必要と思われるものについては、正しい選択のようです。

于 2009-11-12T16:34:51.093 に答える
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 に答える
3

私はそれがうまくいかないと確信しています - キューは を提供しますpushが、挿入イテレータはpush_frontorを使用することを期待していますpush_backpush_insert_iterator自分で(または好きな名前で)書けない本当の理由はありませんが、少し面倒です...

于 2009-11-12T16:43:52.883 に答える
2

必要なのは(キューに対して espush_inserterを実行する挿入子) です。push私の知る限り、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::queueSTL の基本的なコンテナーの 1 つではありません。std::vector std::dequeこれは、基本的な STL コンテナーの 1 つ (この場合は、またはの順次コンテナーの 1 つ) を使用して構築されるコンテナー アダプターstd::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 に答える