CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 8 of 8
  1. #1
    Join Date
    Jun 2002
    Location
    Vienna, Austria
    Posts
    47

    derive from STL's set::iterator

    Hi !

    deriving from list::iterator and vector::iterator is no problem, but how can I derive from set::iterator ?

    I've tried
    Code:
    template < class T, class Pred = less<T>, class A = allocator< T > > 
    class MySetIt : public set< T, Pred, A >::iterator
    {
    };
    
    set< CString* > s;
    MySetIt< CString* > it;
    it = s.begin(); // <= Compile error C2440
    and always get the compile error C2440 (cannot convert from ... to ...)

    How can I derive the iterator ?
    which constructor do I have to provide ?

    Thanks !!

  2. #2
    Join Date
    Apr 1999
    Posts
    27,449

    Re: derive from STL's set::iterator

    Originally posted by corcor
    Hi !

    deriving from list::iterator and vector::iterator is no problem,
    Yes there is a problem -- the iterator classes have no virtual destructor. You should not derive from classes that lack a virtual destructor for reasons that have been discussed here very thoroughly.

    Regards,

    Paul McKenzie

  3. #3
    Join Date
    Jun 2002
    Location
    Vienna, Austria
    Posts
    47
    Hi Paul !

    Thanks for your fast answer.

    I need no destructor, because I only introduce some new methods, e.g.:
    Since I only have pointers in my lists, sets,... and want to access them directly, without always writing
    Code:
     (*it)->myFunction();
    So I declare a new operator
    Code:
    const T operator->(){return operator*();}
    so I simply can write
    Code:
     it->myFunction();

  4. #4
    Join Date
    Apr 1999
    Posts
    27,449
    Originally posted by corcor
    I need no destructor,
    Every class has a destructor, whether you need one or not.

    Regards,

    Paul McKenzie

  5. #5
    Join Date
    Apr 1999
    Posts
    27,449
    Also, are you aware of the problems of deriving from a class that have no virtual destructor? If not, you should read the threads here, or at least go to this link:

    http://www.parashift.com/c++-faq-lit....html#faq-20.5
    As stated there, you need a virtual destructor

    - if someone will derive from your class,
    and

    - if someone will say new Derived, where Derived is derived from your class,
    and

    - if someone will say delete p, where the actual object's type is Derived but the pointer p's type is your class.

    If you can guarantee that no one else will use your code in the way described above, you may be safe for now. But iterators were never meant to be derived from. If they were, their destructors would be virtual.

    Regards,

    Paul McKenzie

  6. #6
    Join Date
    Jun 2002
    Location
    Vienna, Austria
    Posts
    47
    Hi Paul !

    Thanks for your answers.
    Of course every object has a destructor. I ment that I need no virtual destructor, because my derived class won't need one and it's only for my internal functionality, so nobody will derive from my class and nobody will store pointers to the base class.
    STL has no virtual functions at all in order to save the space for the vtable and that's good.

    Regarding my primary question:
    Does anybody know how to derive from an iterator of a set ?

    Many Thanks !!

  7. #7
    Join Date
    Apr 1999
    Posts
    27,449
    First, post a complete example, the sample you posted is missing headers, a main(), etc.

    When compiler errors are the question, it is imperative you post the entire module that won't compile. I tried to come up with code that would duplicate your error, but could not (a different compiler error is displayed).

    Also, I believe the problem is not deriving from a std::set, the problem is your usage of it. There is no operator = that takes your iterator and a set iterator -- that is what the error is plainly stating.

    Believe me, this looks like a bad idea, but you were able to get away with it with vector<> and list<>. Just because you can get away with it doesn't mean it is a good or wise thing to do. All the code that I've seen that have user-defined iterators shows them being created from scratch, and justifiably so.

    Also, just because you can save a grand total of three keystrokes (regarding your previous message -- instead of "(*it)" you want to write "it") isn't justification to come up with the "solution" of deriving from the iterator classes. It's only three keystrokes, is it worth all of this trouble?

    Regards,

    Paul McKenzie
    Last edited by Paul McKenzie; January 28th, 2004 at 07:04 AM.

  8. #8
    Join Date
    Aug 2000
    Location
    West Virginia
    Posts
    7,721
    Maybe create a class that has a set<T>::iterator as
    a member. Something like the following(not tested).

    Note the number of "void"s in the template. Old versions
    of VC++ only have 2, other compilers 4.


    Code:
    #include <set>
    #include <iostream>
    #include <iterator>
    #include <algorithm>
    
    
    template < class T, class Pred = std::less<T>, class A = std::allocator< T > > 
    //class MySetIt : public std::iterator<std::bidirectional_iterator_tag,void,void,void,void>  // g++ , icc , pgCC , etc.
    class MySetIt:public std::iterator<std::bidirectional_iterator_tag,void,void>   // VC++ version 5
    {
    public:
        MySetIt() {}
    
        MySetIt(const MySetIt &it) : m_it(it.m_it) {}
    
        MySetIt(const std::set<T,Pred,A>::iterator &it) : m_it(it) {}
    
        MySetIt & operator ++() { ++m_it; return *this; }
    
        MySetIt   operator ++(int) { MySetIt t = m_it; ++m_it; return t; }
    
        MySetIt & operator --() { --m_it; return *this; }
    
        MySetIt   operator --(int) {MySetIt t = m_it; --m_it; return t; }
    
        T  operator ->() { return *m_it; } // is this what you want ???
    
        const T& operator *() { return *m_it; }
    
        bool operator == (const MySetIt & rhs) const { return m_it == rhs.m_it; }
        bool operator != (const MySetIt & rhs) const { return m_it != rhs.m_it; }
    
        std::set<T,Pred,A>::iterator Get() const { return m_it; }
    
    private:
    
        std::set<T,Pred,A>::iterator m_it;
    };
    
    
    
    using namespace std;
    
    int main()
    {
        std::set<int> s;
        s.insert(1);
        s.insert(2);
        s.insert(3);
    
        MySetIt<int> it1 = s.begin();
        MySetIt<int> it2 = s.end();
    
        copy(it1,it2,ostream_iterator<int>(cout," "));
     
        return 0;
    }
    Last edited by Philip Nicoletti; January 28th, 2004 at 11:04 AM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured