web-dev-qa-db-ja.com

std :: queueをstd :: vectorに変換する方法

並べられたコンテナーとしてのプロパティが優れているため、doubleのキューを使用する必要があります。このキューを、ベクターを受け入れるクラスコンストラクターに渡します。これを直接行うと、次のエラーが発生します。

候補コンストラクタは実行できません:2番目の引数の 'std :: queue'から 'std :: vector&'への既知の変換はありません

キューをベクターにキャストする方法は?

8
Anthony

Queue_like動作とvector-like動作の両方をモデル化するための正しいコンテナは、_std::deque_です。

これには次の利点があります。

  1. デックの両端での一定時間の挿入と削除

  2. 両端キューを破壊せずに要素を反復する機能

_std::deque_はbegin()およびend()メソッドをサポートしています。つまり、(互換性のある値タイプの)ベクトルを直接作成できます。

_#include <vector>
#include <deque>

class AcceptsVectors
{
public:
  AcceptsVectors(std::vector<double> arg);
};

int main()
{
    std::deque<double> myqueue;

    auto av = AcceptsVectors({myqueue.begin(), myqueue.end()});
}
_

queueからvectorへの非変換変換は不可能です。

8
Richard Hodges

std::vectorには イテレータのペアをとるコンストラクタ があるため、キューを反復処理できる場合は設定されます。

この質問 への回答を借用して、std::queueをサブクラス化することで、実際にこれを行うことができます。

template<typename T, typename Container=std::deque<T> >
class iterable_queue : public std::queue<T,Container>
{
public:
    typedef typename Container::const_iterator const_iterator;

    const_iterator begin() const { return this->c.begin(); }                                                                               
    const_iterator end() const { return this->c.end(); }
};

(許可されているのはconst反復のみです。問題の目的のために、要素の変更を許可するイテレータは必要ありません。)

これにより、vectorを簡単に作成できます。

#include <queue>
#include <vector>

using namespace std;

template<typename T, typename Container=std::deque<T> >
class iterable_queue : public std::queue<T,Container>
{
public:
    typedef typename Container::const_iterator const_iterator;

    const_iterator begin() const { return this->c.begin(); }                                                                               
    const_iterator end() const { return this->c.end(); }
};

int main() {
    iterable_queue<int> int_queue;
    for(int i=0; i<10; ++i)
        int_queue.Push(i);

    vector<int> v(int_queue.begin(), int_queue.end());
    return 0;
}
5
Ami Tavory

直接利用できる方法はないと思います。したがって、これは要素を1つずつベクトルに追加することで実現できます。

_std::vector<int> v;
while (!q.empty())
{
    v.Push_back(q.front());
    q.pop();
}
_

この後、キューは空になることに注意してください。

コメントの@Davidで提案されているように、キューの要素をコピーしないようにするとよいでしょう(特に、含まれているオブジェクトが大きい場合に役立ちます)。同じことを行うには、emplace_back()std::move()とともに使用します。

_v.emplace_back(std::move(q.front()));
_
4
CinCout

これは単なるstd::queueからstd::vectorへのコピーを回避するためのアプローチです。使用するかしないかはあなた次第です。

前提

std::queueはコンテナアダプタです。内部containerはデフォルトでstd::dequeですが、std::vectorに設定することもできます。このコンテナを保持するメンバー変数は、幸運にもprotectedとマークされています。したがって、queueをサブクラス化することでハックできます。

解決 (!)

template<typename T>
struct my_queue : std::queue<T, std::vector<T>>
{
  using std::queue<T, std::vector<T>>::queue;
  // in G++, the variable name is `c`, but it may or may not differ
  std::vector<T>& to_vector () { return this->c; }
};

それでおしまい!!

使用法

my_queue<int> q;
q.Push(1);
q.Push(2);
std::vector<int>& v = q.to_vector();

デモ

2
iammilind