简体   繁体   中英

C++: Using any iterator type in a faux-STL class?

I'm creating a container class very similar to a vector (class project), and have defined an iterator subclass. One of the ctors takes two iterator arguments, and builds the data structure (doubly linked list) using the half-open range they represent.

The code below (almost) works for cases when insert(iterator, iterator) is called with two iterators of type Sol::iterator (for some reason, *ita always points to the right values, but the insert(*ita) call doesn't seem to add the value??). The (larger) problem is that the insert call needs to work for all iterator types (ex. vector::iterator), and I haven't been able to track down how to make that work. I've tried typedef / typename T::iterator iterator, but the quietest g++ has been was with 'typename T::iterator iterator', and it returns

g++ ex1.cc -o sol -Wall -Wextra -ansi -pedantic
In file included from ex1.cc:1:0:
Sol.h:87:16: error: expected ‘)’ before ‘ita’
ex1.cc:109:5: error: expected ‘}’ at end of input
In file included from ex1.cc:1:0:
Sol.h:84:3: error: expected unqualified-id at end of input
make: *** [ex1] Error 1

which doesn't make much sense; at least to me. Here's the broad strokes:

template <class T, int find_val = 1, class Compare = std::less<T> >
class Sol{

public:
    typedef unsigned int size_type; //typedef'ing class variable types
    typedef T key_type; 
    typedef T value_type; 
    //typename T::iterator iter;

private:

    struct node{ //Used as 'links' in the chain that is the doubly linked list
        T data;
        node *prev;
        node *next;
    };

    node *head, *tail; //The head and tail of the dll
    int find_promote_value; //How much should find() shift a value?

public:
    class iterator{
        private:
            node *no;
            friend class Sol;
            iterator(node *p) : no(p){
            }
        public:
            iterator() : no(0){
            }

            iterator operator++(){ //Preincrement
                no = no->next;
                return *this;
            }

            iterator operator++(int){ //Postincrement
                iterator temp = *this;
                ++*this;
                return temp;
            }

            iterator operator--(){  //Predecrement
                no = no->prev;
                return *this;
            }

            iterator operator--(int){  //Postdecriment
                iterator temp = *this;
                --*this;
                return temp;
            }

            T operator*(){
                return no->data;
            }

            T *operator->(){
                return &no->data;
            }

            bool operator==(const iterator &rhs){
                return no == rhs.no;
            }

            bool operator!=(const iterator &rhs){
                return no != rhs.no;
            }       
    };

    Sol() : head(0), tail(0), find_promote_value(find_val){
    }

    Sol(const Sol &rhs) : head(rhs.head), tail(rhs.tail), find_promote_value(rhs.find_promote_value){
    }

    typename T::iterator iterator;
    Sol(iterator ita, iterator itb){ //Sol.h::87. Problem line
        while (ita != itb){
            iterator itr = insert(*ita);
std::cout << "Inserting " << *ita << ",printout: " << *itr <<"\n";
//dump();
            ++ita;
        }
    }

    ~Sol(){
        clear();
    }

    iterator insert(T input){
        node *n = new node;
        n->next = NULL;
        n->prev = tail;
        n->data = input;

        if(!tail){
            head = n;
            tail = n;
        }
        else{
            tail->next = n;
            tail = n;
        }

        return iterator(tail);
    }
   };

The (larger) problem is that the insert call needs to work for all iterator types (ex. vector::iterator), and I haven't been able to track down how to make that work.

The fact that you need this to work for all iterator types is an indication that it should be a templated function. If you look at the insert() functions provided by the std::list container, you'll see that one of them has the following declaration:

template <class InputIterator>
void insert(iterator position, InputIterator first, InputIterator last);

Which allows it to use any type for first and last (which specify the half-open range to insert) as long as that type provides the operations that the insert() function uses. You should consider doing something similar. As long as your insert() function only does the following things to those parameters, you should be able to use pretty much any iterator (except an output iterator):

  • compare
  • dereference
  • increment

您在iterator类的末尾缺少分号。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM