Interface do modelo Lista

#ifndef LISTA_H
#define LISTA_H

// Um modelo de classe para representar o conceito de lista.  O único
// argumento do modelo é o tipo dos itens na lista.  O tipo dos itens
// deve possuir construtor por omissão.
template<class I>
class Lista {
  public:
    // É definido sinónimo do tipos de item (util para o utilizador do
    // modelo):
    typedef I Item;

    // Declaração de duas classes embutidas usadas para percorrer as listas:
    class Iterador;
    class IteradorConstante;

    // Construtores e destrutor:
    Lista();                    // construtor por omissão.
    Lista(const Lista& lista);  // construtor por cópia.
    ~Lista();                   // destrutor.

    // Atribuição por cópia:
    Lista& operator = (const Lista& lista);

    // Remove todos os itens da lista:
    void limpa();

    // Informação acerca do tamanho do lista:
    int comprimento() const;    // número de itens.
    bool vazia() const;         // lista vazia?

    // Acesso aos itens nos extremos da lista.  A acesso permite alterações
    // apenas se a lista não for constante:
    I frente() const;           // como primeiro, mas primeiro() devolve iterador.
    I& frente();
    I tras() const;             // como último, mas ultimo() devolve iterador.
    I& tras();

    // Insere novo item no início e no fim da lista, respectivamente:
    void poeInicio(const I& item);
    void poeFim(const I& item);

    // Remove primeiro e último item da lista, respectivamente:
    void tiraPrimeiro();
    void tiraUltimo();

    // Insere novo item antes do item referenciado pelo iterador:
    void insere(Iterador& i, const I& item);
    void insere(const Iterador& i, const I& item);
    /**
     *  A primeira versão de insere() deixa o iterador referenciando o
     *  elemento original, mas a segunda não faz quaisquer garantias: o
     *  utilizador deve tomar o iterador como inválido após a inserção.
     *  A segunda versão serve para se poder inserir usando iteradores
     *  temporários.  Por exemplo:
     *      Lista<int> l;
     *      l.poeFim(1);
     *      l.poeFim(2);
     *      l.insere(l.procura(1), 3);
     */

    // Remove item referenciado pelo iterador:
    void remove(Iterador& i);
    void remove(const Iterador& i);
    // Ver comentários acerca das versões de insere.

    // Concatena a lista passada como argumento com a lista implícita:
    Lista& operator += (const Lista& lista);

    // Transfere todos os itens da lista passada como argumento para o final
    // da lista implícita:
    void transfere(Lista& lista);

    // Devolução de iteradores:
    Iterador primeiro();        // para o primeiro item.
    Iterador ultimo();          // para o último item.
    Iterador fim();             // para o item fictício depois do último.
    Iterador inicio();          // para o item fictício antes do primeiro.
    Iterador procura(const I& item); // para o primeiro item com valor dado.
    Iterador procuraUltimo(const I& item); // para o último item com valor dado.

    // Idem para listas constantes (devolvem iteradores constantes):
    IteradorConstante primeiro() const;
    IteradorConstante ultimo() const;
    IteradorConstante fim() const;
    IteradorConstante inicio() const;
    IteradorConstante procura(const I& item) const;
    IteradorConstante procuraUltimo(const I& item) const;

    // Excepções:
    ...

  private:
    ...
};
 

// Excepções de Lista:
...
 

/**
 * Classe Iterador.  As instâncias servem para percorrer os itens nas listas,
 * permitindo aceder ao seu conteúdo.  Não existe construtor por omissão!
 * Os itens são alteráveis através do iterador.
 */
template<class I>
class Lista<I>::Iterador {
  public:
    // Construtor por omissão não existe.  Um iterador tem de ser criado
    // dizendo qual a lista a que deve ser associado.  Fica associado ao
    // primeiro item da lista:
    explicit Iterador(Lista& lista);

    // Operações de avanço e recuo:
    Iterador& operator ++ ();
    Iterador operator ++ (int);
    Iterador& operator -- ();
    Iterador operator -- (int);

    // Acesso ao item:
    I& item() const;

    // Comparação de iteradores:
    bool operator == (const Iterador& i) const;
    bool operator == (const IteradorConstante& i) const;
    bool operator != (const Iterador& i) const;
    bool operator != (const IteradorConstante& i) const;

    // Excepções:
    ...

  private:
    ...

    // Quer a lista quer os iteradores constantes são amigos:
    friend class Lista;
    friend class IteradorConstante;
};
 

// Excepções de Lista::Iterador:
...
 

// Como a classe Iterador, mas não permitindo alterar os itens referenciados.
template<class I>
class Lista<I>::IteradorConstante {
  public:
    explicit IteradorConstante(const Lista&);
    IteradorConstante(const Iterador& i);

    IteradorConstante& operator ++ ();
    IteradorConstante operator ++ (int);
    IteradorConstante& operator -- ();
    IteradorConstante operator -- (int);

    I item() const;

    bool operator == (const IteradorConstante& i) const;
    bool operator == (const Iterador& i) const;
    bool operator != (const IteradorConstante& i) const;
    bool operator != (const Iterador& i) const;

    ...

  private:
    ...

    friend class Lista;
    friend class Iterador;
};
 

// Excepções de Lista::IteradorConstante:
...

// Implementação:
...

#endif