Insert into an Stl Queue Using Std::Copy

Insert into an STL queue using std::copy

Unfortunately std::queue 'adapts' the function known as push_back to just push which means that the standard back_insert_iterator doesn't work.

Probably the simplest way (albeit conceptually ugly) is to adapt the container adapter with a short lived container adapter adapter[sic] (eugh!) that lives as long as the 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;
};

Used like this:

std::queue<int> qi;

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

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

copy vector into queue

myQueue is a pointer, not a queue, and can’t be passed to std::back_inserter. To fix this, don’t declare it as a pointer.

Furthermore, std::back_inserter can’t be used with a std::queue, as the second link you posted explains.

Instead, simply write

std::queue<OrderInfo*> myQueue{
std::deque<OrderInfo*>(vec.begin(), vec.end())
};

If you really need a pointer, adapt the code as follows:

std::queue<OrderInfo*>* myQueue = new std::queue<OrderInfo*>{
std::deque<OrderInfo*>(vec.begin(), vec.end())
};

Lastly, if you need to fill an already initialised queue, proceed as follows: create a temporary queue using the above and assign it to your pointer:

*myQueue = std::queue<OrderInfo*>{std::deque<OrderInfo*>(vec.begin(), vec.end())};

If this looks too messy you can also create a temporary variable for that queue — but in that case you need to use std::move to ensure that the queue gets move-assigned, not expensively copied:

auto tmp = std::queue<OrderInfo*>{std::deque<OrderInfo*>(vec.begin(), vec.end())};
*myQueue = std::move(tmp);

In the same vein, consider carefully whether you want to store OrderInfos rather than pointers to OrderInfos.

How can I copy an entire vector into a queue?

If you make a new queue, you can use the constructor:

std::vector<int> v = get_vector();

std::queue<long int, std::deque<long int>> q(std::deque<long int>(v.begin(),
v.end()));

(You can change the underlying container to taste, though deque is probably the best.)

If the queue already exists, there's no range-based algorithm, though, you can easily write your own:

template <typename Iter, typename Q>
push_range(Q & q, Iter begin, Iter end)
{
for ( ; begin != end; ++begin)
q.push(*begin);
}

As an aside: If your algorithm requires that amount of flexibility, you're probably better of just using a std::deque in the first place. The container adapters (queue and stack) should only be used if you want to say explicitly, "this is the behaviour I want" (i.e. push/pop).

How do I insert queue elements into a vector?

You have not allocated any of the 5 queues. Try:

typedef std::queue<MyObject*> InputQueue;
std::vector<InputQueue> inp_queue(5);
inp_queue[1].push(new MyObject());

Also not that std::vector uses indices starting from 0, so to insert into the first queue:

inp_queue[0].push(new MyObject());

Follow-up to your edit: The concurrent queue does not seem to have a copy constructor. This means you can not put it in any standard container because it does not satisfy the requirements. The container's value-type must be copy-constructible and copy-assignable.

does queue create a copy?

It will get copied as you assign an rvalue reference. It will get moved if you assign an lvalue reference. (temporary object).

To check, use copy constructor / operator and move constructor / operator overloading:

#include <iostream>
#include <vector>
#include <queue>

struct Node {
int x;
int y;

Node(int x, int y) : x(x), y(y)
{
std::cout << "constructor" << std::endl;
}

Node(Node const & original) : x(original.x), y(original.y)
{
std::cout << "copy constructor" << std::endl;
}

Node(Node const && original) : x(original.x), y(original.y)
{
std::cout << "move constructor" << std::endl;
}

Node & operator=(Node const & original) {
std::cout << "assignment operator" << std::endl;
if(this != &original) {
x = original.x;
y = original.y;
}
return *this;
}

Node & operator=(Node const && original) {
std::cout << "move operator" << std::endl;
if(this != &original) {
x = original.x;
y = original.y;
}
return *this;
}
};

int main() {

std::vector<Node> v;

Node n(1,3); // constructor
Node m(3, 4); // constructor

m = n; // assignment operator
n = Node(2, 3); // constructor + move operator

v.push_back({1,2}); // constructor + move constructor
v.push_back(n); // copy constructor

std::queue<Node> q;
q.push(v[0]); // copy constructor

return 0;
}

Using std::copy to copy into an std::deque

I do not see any sense to allocate buffer in the heap. Nevertheless the valid code will look like

std::deque<unsigned char>* buffer = new std::deque<unsigned char>();
std::copy( Temp, Temp + SERVER_BUFFER_SIZE, std::back_inserter( *buffer ) );

Here is a demonstrative program

#include <iostream>
#include <deque>
#include <iterator>

int main()
{
const size_t SERVER_BUFFER_SIZE = 6;
unsigned char Temp[SERVER_BUFFER_SIZE] = "Hello";

std::deque<unsigned char> *buffer = new std::deque<unsigned char>();

std::copy( Temp, Temp + SERVER_BUFFER_SIZE, std::back_inserter( *buffer ) );

for ( unsigned char c : *buffer ) std::cout << c;
std::cout << std::endl;

delete buffer;

return 0;
}

The output is

Hello

avoid copys when pushing an element into std::queue

If and only if X supports move semantics the first is is fine.

X might be like:

struct X {
int value;
X() {
static int n;
value = ++n;
}

X(X&&) = default;
X& operator = (X&&) = default;

X(const X&) = delete;
X& operator = (const X&) = delete;
};

Note: No copy of X is allowed, here.



Related Topics



Leave a reply



Submit