Solved

C++ bidirectional iterators for array of classes

Posted on 2013-11-13
1
395 Views
Last Modified: 2013-11-13
I need an ordered list of classes (Items), and a bidirectional iterator that can go forwards or backwards through the ordered list, changing direction as I please.

Also if I'm at the end of the ordered list and seek the 'next' entry, I'd like to wrap around to the first entry. Similarly, if I'm at the beginning of the ordered list and seek the 'previous' entry, I'd like to wrap around to the last entry.

Currently I'm attempting to do this with a vector:
MyClass.h
class MyClass
{
private:
    std::vector<class Item*> myItems;
    std::vector<class Item*>::iterator currentItem;
public:
    Item* GetCurrentItem();
    Item* NextItem();
    Item* PrevItem();
    void  AddItem(Item *s);
};

Open in new window


MyClass.cpp
#include "StdAfx.h"
#include "MyClass.h"

Item* MyClass::GetCurrentItem()
{
    Item* s;
    s = *currentItem;
    return s;
}
void MyClass::AddItem(Item *s)
{
    myItems.push_back(s);
}

Item* MyClass::NextItem()
{
    Item* s;
    currentItem++;
    if (currentItem == myItems.end()) {currentItem = myItems.begin();}
    s = *currentItem;
    return s;
}

Item* MyClass::PrevItem()
{
    Item* s;
    currentItem--;
    if (currentItem == myItems.begin() - 1) {currentItem = myItems.end() - 1;}
    s = *currentItem;
    return s;
}

Open in new window


At this point I start thinking someone must have already invented what I'm trying to reinvent here.

Plus I have a problem when I add the tag std::bidirectional_iterator_tag so I can randomly travel both forwards and backwards as I please:
MyClass.h
class MyClass
{
private:
    std::vector<std::bidirectional_iterator_tag, class Item*> myItems;
    std::vector<std::bidirectional_iterator_tag, class Item*>::iterator currentItem;
public:
    Item* GetCurrentItem();
    Item* NextItem();
    Item* PrevItem();
    void       AddItem(Item *s);
};

Open in new window

I now get complaints about the code
void MyClass::AddItem(Item *s)
{
    myItems.push_back(s);
}

Open in new window

no instance of overloaded function "std::vector<_Ty, _Ax>::push_back [with _Ty=std::bidirectional_iterator_tag, _Ax=Item *]" matches the argument list    
This is getting complicated. Does C++ offer something besides vector which has the simple abilities I seek? Or, how can I modify the above so it works? (Do I even need to specify std::bidirectional_iterator_tag?)
0
Comment
Question by:deleyd
1 Comment
 
LVL 86

Accepted Solution

by:
jkr earned 500 total points
ID: 39646298
>>Do I even need to specify std::bidirectional_iterator_tag?

Err, no - you can just go with the regular iterators, both '++' and '--' are defined for them. This tag is used to describe the 'bidirectional' attribute when quering for an iterator's traits at run time via RTTI, e.g.

#include <iterator>
#include <vector>
#include <iostream>
#include <list>

using namespace std;

int main( )
{
   vector<int> vi;
   vector<char> vc;
   list<char> lc;
   iterator_traits<vector<int>:: iterator>::iterator_category cati;
   iterator_traits<vector<char>:: iterator>::iterator_category catc;
   iterator_traits<list<char>:: iterator>::iterator_category catlc;

   // These are both random-access iterators
   cout << "The type of iterator for vector<int> is "
       << "identified by the tag:\n " 
       << typeid ( cati ).name( ) << endl;
   cout << "The type of iterator for vector<char> is "
       << "identified by the tag:\n " 
       << typeid ( catc ).name( ) << endl;
   if ( typeid ( cati ) == typeid( catc ) )
      cout << "The iterators are the same." << endl << endl;
   else
      cout << "The iterators are not the same." << endl << endl;

   // But the list iterator is bidirectinal, not random access
   cout << "The type of iterator for list<char> is "
       << "identified by the tag:\n " 
       << typeid (catlc).name( ) << endl;

   // cout << ( typeid ( vi.begin( ) ) == typeid( vc.begin( ) ) ) << endl;
   if ( typeid ( vi.begin( ) ) == typeid( vc.begin( ) ) )
      cout << "The iterators are the same." << endl;
   else
      cout << "The iterators are not the same." << endl;
   // A random-access iterator is a bidirectional iterator.
   cout << ( void* ) dynamic_cast< iterator_traits<list<char>:: iterator>
          ::iterator_category* > ( &catc ) << endl;
}

Open in new window


Output:

The type of iterator for vector<int> is identified by the tag:
 struct std::random_access_iterator_tag
The type of iterator for vector<char> is identified by the tag:
 struct std::random_access_iterator_tag
The iterators are the same.

The type of iterator for list<char> is identified by the tag:
 struct std::bidirectional_iterator_tag
The iterators are not the same.
0012FF3B

Open in new window


(Example taken from MSDN)

>>Does C++ offer something besides vector which has the simple abilities I seek?

Both 'list' and 'vectorÄ iterators are already bidirectional. The codee you have in the first two snippets will already do what you asked for.

CAVEAT: Vector iterators will be invalidated once you add an item or remove one from the container. List iterators will stay valid, though.
0

Featured Post

Top 6 Sources for Identifying Threat Actor TTPs

Understanding your enemy is essential. These six sources will help you identify the most popular threat actor tactics, techniques, and procedures (TTPs).

Join & Write a Comment

Often, when implementing a feature, you won't know how certain events should be handled at the point where they occur and you'd rather defer to the user of your function or class. For example, a XML parser will extract a tag from the source code, wh…
This article will show you some of the more useful Standard Template Library (STL) algorithms through the use of working examples.  You will learn about how these algorithms fit into the STL architecture, how they work with STL containers, and why t…
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.

760 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now