Getting index of an element in a std::queue by its value

If you want to get the index of an element you should probably consider using an std::deque container instead of a std::queue container adapter, as already suggested in this other answer.


If you still want to stick to to the std::queue container adapter for some other reason, you should know that it does provide access to the underlying container through the protected data member c.

You could derive from std::queue in order to access the underlying container and use the std::find() function template for finding an element in that container with such a value. Then, simply return the position of that element by using std::distance().

#include <algorithm>
#include <queue>

template<typename T>
class Queue: std::queue<T> {
public:
   auto getPosition(const T& val) const {
      auto it = std::find(this->c.begin(), this->c.end(), val);
      return std::distance(this->c.begin(), it);
   }
// ...
};

If the element is not found, the index will correspond to the one returned by the size() member function.

If there are duplicates, this solution based on std::find() will return the position of the first one, i.e., the first element found with the requested value val.


You can use std::deque instead:

#include <algorithm>

std::deque<int> names;

names.push_back(7);
names.push_back(4);
names.push_back(11);

auto it = std::find(names.begin(), names.end(), 4);
if(it != names.end())
    int distance = it - names.begin();
else
    //no element found

Note that std::queue uses std::deque as default implementation, so any operations take the same time as in queue.

std::deque also supports random access, so names[0] will return 7. It can also be used like any other queue:

std::deque<int> myDeque{};
myDeque.push_back(5);
myDeque.push_back(13);
std::cout << myDeque.front(); //5
myDeque.pop_front();
std::cout << myDeque.front(); //13

An alternative generic way is defining the following new container which is an inheritance of std::queue and defines begin() and end() returning iterators of the protected member std::queue::c. Then you can use various STL algorithms with this container:

#include <queue>

template<
    class T,
    class Container = std::deque<T>
>
class Queue : public std::queue<T, Container>
{
public:
    using iterator               = typename Container::iterator;
    using const_iterator         = typename Container::const_iterator;
    using reverse_iterator       = typename Container::reverse_iterator;
    using const_reverse_iterator = typename Container::const_reverse_iterator;

    iterator        begin()       noexcept { return this->c. begin(); }
    const_iterator  begin() const noexcept { return this->c.cbegin(); }
    const_iterator cbegin() const noexcept { return this->c.cbegin(); }

    iterator        end()       noexcept { return this->c. end(); }
    const_iterator  end() const noexcept { return this->c.cend(); }
    const_iterator cend() const noexcept { return this->c.cend(); }

    reverse_iterator        rbegin()       noexcept  { return this->c. rbegin(); }
    const_reverse_iterator  rbegin() const noexcept  { return this->c.crbegin(); }
    const_reverse_iterator crbegin() const noexcept  { return this->c.crbegin(); }

    reverse_iterator        rend()       noexcept  { return this->c. rend(); }
    const_reverse_iterator  rend() const noexcept  { return this->c.crend(); }
    const_reverse_iterator crend() const noexcept  { return this->c.crend(); }
};

...Yes, as it is well known, STL containers have no virtual destructors. The destruction of this derived class through the base class pointers causes undefined behavior. Thus I would suggest using the above derived class if and only if you really need it.


For the current position problem, you can find the position where the first element found as follows:

DEMO

#include <algorithm>
#include <iterator>

Queue<int> q;
q.push(7);
q.push(4);
q.push(11);

const auto it = std::find(q.cbegin(), q.cend(), 4);
const auto position = std::distance(q.cbegin(), it); //should be 1

Tags:

C++

Queue

Stl