// Este arquivo tem uma nova versão do exemplo de FunkyVector, que é aquele // vetor que permite indexação com índices negativos para se indicar índice // de trás para frente: -1 é o último elemento, -2 o penúltimo, etc. // Nesta versão temos as seguintes alterações: // 1. Usamos herança, dizendo que um FunkyVector é apenas um outro tipo de // vector, e portanto herdando tudo o que é definido para vetor. Precisamos // apenas redefinir o operador de indexação. // 2. Transformamos o FunkyVector num template, para podermos ter vetores de // qualquer tipo de elemento. // 3. Definimos uma versão de operador de indexação que pode ser usado em // objetos constantes do tipo FunkyVector. #include #include #include // Um FunkyVector é um molde (template), com elementos do tipo Value. // Ele é também derivado de std::vector, isto é, possui todos os membros // que a classe da biblioteca possui. template class FunkyVector : public std::vector { public: // Queremos usar os construtores de std::vector para FunkyVector, então // precisamos o seguinte using: using std::vector::vector; // O operador de indexação deve retornar uma referência para um elemento, // e cada elemento é do tipo Value. Value &operator[](int i); // Precisamos também de um operador que funcione em vetores constantes. // Para isso precisamos: // - Marcar o método operator[] como const para ele poder ser chamado sobre // um objeto constante. // - Marcara referência retornada como const, para não permitir que o elemento // do vetor referenciado seja alterado (senão o vetor não ficaria constante) Value const &operator[](int i) const; }; // Cada um dos métodos é uma função membro que é também um template, pois // tem que se adaptar ao tipo do elemento carregado pelo vetor. template Value &FunkyVector::operator[](int i) { // Precisamos realizar a chamada implícita do operator[] da classe base // porisso temos essa sintaxe estranha. Se não fazemos isso, teremos uma // recursão infinita. if (i >= 0) { return std::vector::operator[](i); } else { return std::vector::operator[](this->size() + i); } } // A não ser pelos const, as implementações são idênticas. template Value const &FunkyVector::operator[](int i) const { if (i >= 0) { return std::vector::operator[](i); } else { return std::vector::operator[](this->size() + i); } } int main(int, char *[]) { FunkyVector v(10); for (size_t i = 0; i < v.size(); ++i) { v[i] = i; } for (int i = -5; i < 5; ++i) { std::cout << "v[" << i << "] = " << v[i] << std::endl; } FunkyVector str(8); for (size_t i = 0; i < 8; ++i) { str[i] = std::to_string(i) + "-esimo"; } for (int i = -4; i < 4; ++i) { std::cout << "str[" << i << "] = " << str[i] << std::endl; } }