• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 587
  • Last Modified:

iterator

hi all,
 a)   The following my code is as a list. Problem arises while increment iterator (++itr) in the statement
      for(itr = Value.begin(); itr != Value.end(); ++itr)
    Actual problem arises in following statement
      ValueList *operator++()
      {
            return this->next; //here. HOw can I modify this?
      }

If I put here as itr = itr->next the code is working fine in Solaris (not in windows). But I want to increment iterator as ++itr.

b) If I put itr = itr->next in windows the error " 'operator <<' is ambiguous" is  coming
            cout << *itr << endl;
This error is for operator << overloading.

HOw can I overcome from this?
I can implement code in other way (for my project purpose). But I want solution for this.
-Mahesh

#include <iostream>
using namespace std;
#define STR_SIZE 100

struct ValueList
{
      union _Value
      {
            int nValue;
            char caValue[STR_SIZE];
      }Value;

      ValueList *next;
      ValueList *operator++()
      {
            return this->next;
      }
      friend ostream &operator <<(ostream &os,const ValueList &x);
};
class oidValue
{
      ValueList *vlHead,*vlTail,*vlNode;
public:
      typedef ValueList*           iterator;
      iterator         begin()         {return vlHead;}    
      iterator         end()         {return NULL;}  
      oidValue()
      {
            vlHead = vlTail = NULL;
      }
      bool push_back(const int &x);
      bool push_back(const char *);
      void display();
      ~oidValue();
};

ostream &operator <<(ostream &os,const ValueList &x)
{
      os << x.Value.nValue;
      return os;
}

bool oidValue::push_back(const int &x)
{
      if(vlHead == NULL)
      {
            try
            {
                  vlTail = vlHead = new ValueList;
            }
            catch(bad_alloc)
            {
                  return false;
            }
      }
      else
      {
            try
            {
                  vlTail->next = new ValueList;
            }
            catch(bad_alloc)
            {
                  return false;
            }
            vlTail = vlTail->next;
      }
      vlTail->next = NULL;
      vlTail->Value.nValue = x;

      return true;
}

bool oidValue::push_back(const char* x)
{
      if(vlHead == NULL)
      {
            try
            {
                  vlTail = vlHead = new ValueList;
            }
            catch(bad_alloc)
            {
                  return false;
            }
      }
      else
      {
            try
            {
                  vlTail->next = new ValueList;
            }
            catch(bad_alloc)
            {
                  return false;
            }
            vlTail = vlTail->next;
      }
      vlTail->next = NULL;
      memcpy(vlTail->Value.caValue,x,STR_SIZE);
      vlTail->Value.caValue[STR_SIZE]=0;
      return true;
}

oidValue::~oidValue()
{
      while(vlHead != NULL)
      {
            vlNode = vlHead;
            vlHead = vlHead->next;
            delete vlNode;
      }
}
void oidValue::display()
{
      vlNode = vlHead;
      while(vlNode != NULL)
      {
            cout << vlNode->Value.nValue << endl;
            vlNode = vlNode->next;
      }

}
int main()
{
      oidValue Value;
      Value.push_back(99);
      Value.push_back(33);
      Value.push_back(5);
      //Value.display();

      oidValue::iterator itr;
      for(itr = Value.begin(); itr != Value.end(); ++itr)
      {
            cout << *itr << endl;
      }

      return 0;
}
0
smpoojary
Asked:
smpoojary
  • 4
  • 4
1 Solution
 
AxterCommented:
Why are you reinventing the wheel?

If you're using code for multiple platforms, it's far safer to use the STL then to try to do a home grown version of a list or custom container.

I recommend you use std::list instead.
0
 
itsmeandnobodyelseCommented:
>>>>     typedef ValueList*           iterator;

I would assume the typedef has to be moved outside of class oidValue.

I would agree to Axter's recommendation to use std::list instead. A union containing an int and a char array is a poor attempt to simulate a template node and the implementation of ValueList isn't state of the art.

Regards, Alex
0
 
itsmeandnobodyelseCommented:
>>>>           cout << *itr << endl;

That compiles with VC6 compiler (SP4).
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
smpoojaryAuthor Commented:
I had finished my code (used other logic). But I want solution for this.
-Mahesh
0
 
smpoojaryAuthor Commented:
If I use what Alex told then I will get following errors
"test.cpp", line 25: Error: The name iterator is ambiguous, iterator and std::it
erator<std::Category, std::T, std::Distance, std::Pointer, std::Reference>.
"test.cpp", line 26: Error: The name iterator is ambiguous, iterator and std::it
erator<std::Category, std::T, std::Distance, std::Pointer, std::Reference>.
"test.cpp", line 132: Error: The name iterator is ambiguous, iterator and std::i
terator<std::Category, std::T, std::Distance, std::Pointer, std::Reference>.
3 Error(s) detected.

Becuase std aslready as iterator typedef
-Mahesh
0
 
itsmeandnobodyelseCommented:
>>>> Becuase std aslready as iterator typedef

No, it's because you have

    using namespace std;

Then  baseclass

   std::iterator

conflicts with your typedef.

I think I was wrong with my suggestion a global typedef could solve the problem. You could check it anyhow by renaming your iterator to Iterator and calling it like

     Iterator itr;  // Note, you have to remove the class scope when making it globally.

     for(itr = Value.begin(); itr != Value.end(); ++itr)
     {
          cout << *itr << endl;
     }

You additionaly could try the following:

ostream &operator <<(ostream &os,const ValueList &x)
{
     os << x.Value.nValue;
     return os;
}
...


int main()
{
    ValueList vlist;
    vlist.Value.nValue = 12345;
    cout << vlist << endl;
    return 0;
}

If that compiles, the typedef should be the problem. If that is ambiguous as well, your compiler seems to have problems with specializing operator<< overloads.

What compiler are you using at Windows? Could you get a newer version?

Regards, Alex





0
 
smpoojaryAuthor Commented:
hi Alex,

a)
    I modified code as you told(rename to Iterator and modified inside main() ). It is giving correct result
bash-2.03$ ./a.out
12345

     But if I renamed iterator to Iterator(typedef), defined globally (removed iterator typdef inside class), But if I use my previous code in main() (for loop, ++itr), it compiles properly in Solaris and getting same result while running my previous code (code posted above).
Output
--------
bash-2.03$ ./a.out
99
105
0
0
1
399624
0
0
0
0
0
...
0
0
Segmentation Fault (core dumped)

I think this is becuase problem in operator ++ overloading (as I explained earlier)
    ValueList *operator++()
     {
          return this->next; //here. HOw can I modify this?
     }
Becuase in my posted code above (in question) if I use itr = itr->next instead of ++itr inside for loop the code is working fine in Solaris (I explained this in my question also). Getting correct result
Output
-------
99
33
5

b)  In windows I am using VC6. In windows same error (as I explained earlier) is coming after modified as you told
    The error is in main() the line          cout << vlist << endl;
    error:  "operator <<' is ambiguous"

-Mahesh
0
 
itsmeandnobodyelseCommented:
>>>> I modified code as you told(rename to Iterator and modified inside main() ). It is giving correct result

Ok. That should mean that the name 'iterator' couldn't/shouldn't be used cause there are similar typedefs in STL that make problems when using the namespace std as default. I would assume using a different name isn't a big problem.

>>>>    ValueList *operator++()
>>>>     {
>>>>          return this->next; //here. HOw can I modify this?
>>>>     }

I think I detected the problem. The operator above is never used, cause it operates on ValueList objects and *not* on ValueList pointers.  That means:

   ValueList vl;
   vl.next = NULL;
   vl++;          

With that code your operator++ function might be called, though I wouldn't bet on it cause it has the wrong prototype. It should have

   ValueList& operator++();


>>>>      for(itr = Value.begin(); itr != Value.end(); ++itr)

Here ++itr simply does  itr = itr + 1; what is pointer arithmetic and means that the address was incremented by pointer size (normally 4 bytes). That could work if 'new ValueList' incidentally uses the next 4 byte allocation, but normally allocation happens using bigger chunks - especially in debug mode.

What to do?

If you really want to use that class - still think that a standard container would be the much better choice - you need to define a 'nested' iterator class. For that class you could provide an operator++ that really would be called.

class oidValue
{
     ValueList *vlHead,*vlTail,*vlNode;
public:
     class iterator
     {
           ValueList*   pCur;
     public:
           iterator(ValueList* p = NULL) :  pCur(p) {}
           iterator& operator++() { if (pCur != NULL) pCur = pCur->next; return *this; }
           iterator  operator++(int) { iterator* p = this; if (pCur != NULL) pCur = pCur->next; return *p; }
           const ValueList& operator*() { return *pCur; }
           const ValueList* operator->() const { return pCur; }
           bool operator!= (const iterator& it) const { return pCur != it.pCur; }
     };
     iterator         begin()       {return vlHead;}    
     iterator         end()         {return NULL;}  
     oidValue()
     {
          vlHead = vlTail = NULL;
     }
     bool push_back(const int &x);
     bool push_back(const char *);
     void display();
     ~oidValue();
};


I tried that in a test project (XP/VC6) but got the ambiguity compiler error on cout you posted in your initial question. I had to remove 'friend ostream& operator<<' declaration in struct ValueList - what doesn't matter as all members are public anyway - to get rid of it. Seems to be a bug in VC6 that happens if you don't use inline code (I remember that I had this sometimes before).

Regards, Alex



   

   




0
 
smpoojaryAuthor Commented:
Alex,

    Now code is working fine in Solaris as well as in windows.
    thanks a lot. You know what is inside in C++.

    Thanks for Axter also.

    with warm regards
    -Mahesh

#include <iostream>
using namespace std;
#define STR_SIZE 100

struct ValueList
{
      union _Value
      {
            int nValue;
            char caValue[STR_SIZE];
      }Value;
      ValueList *next;
};

ostream &operator <<(ostream &os,const ValueList &x)
{
     os << x.Value.nValue;
     return os;
}

class oidValue
{
     ValueList *vlHead,*vlTail,*vlNode;
public:
     class iterator
     {
           ValueList*   pCur;
     public:
           iterator(ValueList* p = NULL) :  pCur(p) {}
           iterator& operator++() { if (pCur != NULL) pCur = pCur->next; return *this; }
           iterator  operator++(int) { iterator* p = this; if (pCur != NULL) pCur = pCur->next; return *p; }
           const ValueList& operator*() { return *pCur; }
           const ValueList* operator->() const { return pCur; }
           bool operator!= (const iterator& it) const { return pCur != it.pCur; }
     };
     iterator         begin()       {return vlHead;}    
     iterator         end()         {return NULL;}  
     oidValue()
     {
          vlHead = vlTail = NULL;
     }
     bool push_back(const int &x);
     bool push_back(const char *);
     void display();
     ~oidValue();
};

bool oidValue::push_back(const int &x)
{
      if(vlHead == NULL)
      {
            try
            {
                  vlTail = vlHead = new ValueList;
            }
            catch(bad_alloc)
            {
                  return false;
            }
      }
      else
      {
            try
            {
                  vlTail->next = new ValueList;
            }
            catch(bad_alloc)
            {
                  return false;
            }
            vlTail = vlTail->next;
      }
      vlTail->next = NULL;
      vlTail->Value.nValue = x;

      return true;
}

bool oidValue::push_back(const char* x)
{
      if(vlHead == NULL)
      {
            try
            {
                  vlTail = vlHead = new ValueList;
            }
            catch(bad_alloc)
            {
                  return false;
            }
      }
      else
      {
            try
            {
                  vlTail->next = new ValueList;
            }
            catch(bad_alloc)
            {
                  return false;
            }
            vlTail = vlTail->next;
      }
      vlTail->next = NULL;
      memcpy(vlTail->Value.caValue,x,STR_SIZE);
      vlTail->Value.caValue[STR_SIZE]=0;
      return true;
}

oidValue::~oidValue()
{
      while(vlHead != NULL)
      {
            vlNode = vlHead;
            vlHead = vlHead->next;
            delete vlNode;
      }
}
void oidValue::display()
{
      vlNode = vlHead;
      while(vlNode != NULL)
      {
            cout << vlNode->Value.nValue << endl;
            vlNode = vlNode->next;
      }

}
int main()
{

      oidValue Value;
      Value.push_back(99);
      Value.push_back(33);
      Value.push_back(5);
      //Value.display();

      oidValue::iterator itr;
      for(itr = Value.begin(); itr != Value.end(); ++itr)
      {
            cout << *itr << endl;
      }

      return 0;
}
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 4
  • 4
Tackle projects and never again get stuck behind a technical roadblock.
Join Now