beginner_intermediate

Range loops – Escrevendo código seguro

Eu estava olhando um código de um sistema e me deparei com um trecho que me fez torcer o nariz. O código funcionava, mas imediatamente vi dois problemas potenciais:

  1. Bug de int/unsigned int
    1. Um vector::size() – 1
    2. Se size for 0, o resultado será 4294967295 ou 0xFFFFFFFF!
  2. Código confuso e facilmente quebrável
    1. msgs[count] – Não tem offset dinâmico
    2. Um count inválido pode quebrar o programa

Eu suponho que a pessoa que desenvolveu o código fez dessa forma para pegar os itens que estavam no vector, excluindo os itens da borda (0:n), mas como seria essa implementação da forma STL de se programar ?

Três possibilidades

Todas elas tem um problema com relação à implementação original. A implementação original pega o range de [1:size-1). Estas formas que eu apresentei pegam o range de [0:size). Como fazer então ?

A forma mais inocente e com os mesmos problemas da implementação que eu vi seria:

Se o tamanho do vector for 0, msgs.cbegin() == msgs.cend(), e teremos um problema, pois msgs.cbegin()+1 estaria apontando para uma região da memória mais adiante da apontada por msgs.cend()-1. Vemos também que os outros exemplos de ranged-for não nos dão a possibilidade de mudar o intervalo com offsets. Qual seria a solução então ?

A definição de um container no qual é possível executar iterações, (grosseiramente) é um objeto que possui as funções begin e end. Então, fiz uma solução interessante para o caso, algo parecido ou no estilo de uma view.

Solução adequada – Range!

Para começar, precisamos de uma estrutura que implemente um range

Agora já temos a nossa estrutura contendo begin e end e dois iteradores. Só falta criarmos uma função que aponte os iteradores para um container definindo o range [1:size-1)

Temos agora uma função que retorna de forma segura o range [1:size-1) mesmo quando o vetor é vazio ou contém menos de dois elementos.

Segue abaixo um exemplo de uso da função narrow_range

Fontes:
https://github.com/SimplyCpp/examples/blob/master/loop1.cpp
https://github.com/SimplyCpp/examples/blob/master/loop2.cpp

1 Comment

Leave a Reply

Your email address will not be published. Required fields are marked *