Erik
Erik

Reputation: 7352

Modifying standard STL containers so support generic queue interface

I'm interested in creating a function that uses a queue as part of its implementation, but I want to be templated on the type of queue so that it will have different functionality based on what type of queue its templated with.

Here's a basic example:

template <typename Queue>
void example()
{
  Queue a;
  a.push(3);
  a.push(1);
  a.push(2);
  while (!a.empty()) {
    cout << a.top() << ' ';
    a.pop();
  }
  cout << flush;
}

What I want is for example<stack<int>>() to print 2 1 3, example<priority_queue<int>>() to print 3 2 1, and example<queue<int>>() to print 3 1 2. This works for stack and priority_queue but unfortunately queue doesn't provide top and instead provides front. Is there an easy way to tell the compiler when it sees top on a queue to call front instead?

The only way around this that I can think of is to follow this question How to implement generic method for STL containers that haven`t common interface needed for that method using template template parameter, and implement my own local top for each of the data types and call that instead. This solution seems super inelegant though, and I'd rather find another way if possible.

Edit: I am using a compiler that supports C++11, gcc 4.7.0 to be exact.

Upvotes: 2

Views: 176

Answers (1)

Dietmar K&#252;hl
Dietmar K&#252;hl

Reputation: 154015

Assuming the presence of a top() and a front() member are mutually exclusive, you could create a suitable top() helper function which is overloaded on the presence of the respective member:

 template <typename Queue>
 auto top(Queue const& queue) -> decltype((queue.top()))
 {
     return queue.top();
 }

 template <typename Queue>
 auto top(Queue const& queue) -> decltype((queue.front()))
 {
     return queue.front();
 }

You can then just use top(a) to access the current top even if the top is called front(). This won't work, however, if a queue has both front() and top(). A simple fix to this problem is to make the choice of the front() version just a bit less attractive to call so it is called if it is the only version but it isn't called if both top() and front() are available. For example:

 template <typename Queue>
 auto top(Queue const& queue, bool) -> decltype((queue.top()))
 {
     return queue.top();
 }

 template <typename Queue>
 auto top(Queue const& queue, int) -> decltype((queue.front()))
 {
     return queue.front();
 }

... and then get access to the top element using top(a, true).

Upvotes: 7

Related Questions