c ++ error passing 'const std :: vectorNode' as 'this' argument discards qualifiers

0

I am implementing a minimal path search algorithm, and I get several errors that I do not understand:

set< vector<Nodo>>&::iterator it;    

for(it=nodos_visitados.begin(); it!=nodos_visitados.end();it++){
  for(int i=(*it);i<(*it).size();i++){
    os<< " Nodo  con puntos " << (*it)[i].get_x() << " y "<< (*it)[i].get_y()<< "  con coste "<< (*it)[i].get_coste()<<endl; //para ningun operador se pone el punto
   }
 }

I get several errors:

error: expected primary-expression before ‘>’ token
         set< vector<Nodo>>&::iterator it;
                         ^~
car.cpp:197:39: error: missing template arguments before ‘it’
         set< vector<Nodo>>&::iterator it;
                                       ^~
car.cpp:200:13: error: ‘it’ was not declared in this scope
         for(it=nodos_visitados.begin(); it!=nodos_visitados.end();it++){

I am learning C ++, my main problem is that I write code and try to look at examples that serve as reference, I try to write little code and compile, but I spend a lot of time debugging code. Thanks

    
asked by AER 13.11.2018 в 20:48
source

1 answer

1

C ++ 98

In C ++ 98, when working with nested templates, it is not legal to leave the closures of them together:

set< vector<Nodo>> variable;
//              ~~

Since that sequence is confused with the extraction operator:

std::cout >> a;

So that you have to leave at least one space between a template closure and the following:

std::set<std::vector<Nodo> > nodos_visitados;
//                       ~~~

Additionally, the iterator is poorly declared. The iterator is an object dependent on the class std::set and, consequently, it gives absolutely the same if the container is using it by value, by reference or by pointers ... the declaration of the iterator will be always the same .

This means that the & in the declaration of the iterator remains:

std::set<std::vector<Nodo> >::iterator it = nodos_visitados.begin();

This line compiles perfectly whether nodos_visitados is a use variable or a reference:

std::set<std::vector<Nodo> >   por_valor;
std::set<std::vector<Nodo> > & referencia = &por_valor;

std::set<std::vector<Nodo> >::iterator it;
it = por_valor.begin();  // OK
it = referencia.begin(); // OK

The only thing that changes in the case of pointers is that we have to use the indirection operator -> instead of . :

std::set<std::vector<Nodo> > * punero = &por_valor;
it = por_valor->begin();

Well, this iterator will go through the set , giving us access to its content. The content of set are vectors, then *it will return a vector . This implies that the second loop is wrong:

for(int i=(*it);i<(*it).size();i++)

We can not convert a std::vector<Nodo> to int . Maybe what you tried was this:

for(int i=0;i<(*it).size();i++)

Although, being strict, the size method does not return an integer but size_t , an alias that in 32 bits usually equals unsigned int and, in 64 bits, a unsigned long long . To avoid silly warnings and, occasionally, erratic behavior, it is advisable to use the correct types:

for(size_t i=0; i<it->size(); ++i)

Of course we can also keep on going through the iterators:

std::vector<Nodo>::const_iterator it2;
for( it2 = it->begin(); it2 != it->end(); ++it2 )
{
  Nodo const& nodo = *it2;
  // ...
}

C ++ 11

C ++ 11 brings some news that you should know.

The first is that it is no longer necessary to separate the closures of the templates. The compilers conforming to this standard are already able to distinguish the cases mentioned above, then nodos_visitados can be declared without spaces:

std::set<std::vector<Nodo>> nodos_visitados;

And the same for the visitor:

std::set<std::vector<Nodo>>::iterator it;

Now, C ++ 11 also incorporates auto . A mechanism that delegates the deduction of the type of variable to the compiler.

So, on the following line:

auto it = nodos_visitados.begin();

it , depending on whether nodos_visitados is constant or not, it could be of the type:

  • std::set<std::vector<Nodo>>::iterator : nodos_visitados no is constant
  • std::set<std::vector<Nodo>>::const_iterator : nodos_visitados is constant

And it also adds less garbage to the code.

Incorporating this change the loops are more readable:

for(auto it=nodos_visitados.begin(); it!=nodos_visitados.end();it++)
{
  for(auto it2 = it->begin(); it2 != it->end(); ++it2)
  {
    os << " Nodo  con puntos "
       << it2->get_x()
       << " y "
       << it2->get_y()
       << "  con coste "
       << it2->get_coste()
       << endl; //para ningun operador se pone el punto
  }
}

Another interesting feature of C ++ 11 is the rank-based for. With this type of loop we save the iterators, since they will be managed transparently by C ++ behind us:

for(std::vector<Nodo> const& lista : nodos_visitados)
{
  for(Nodo const& nodo : lista)
  {
    os << " Nodo  con puntos "
       << nodo.get_x()
       << " y "
       << nodo.get_y()
       << "  con coste "
       << nodo.get_coste()
       << endl; //para ningun operador se pone el punto
  }
}

In these loops we can also use auto :

for(auto const& lista : nodos_visitados)
{
  for(auto const& nodo : lista)
  {
    os << " Nodo  con puntos "
       << nodo.get_x()
       << " y "
       << nodo.get_y()
       << "  con coste "
       << nodo.get_coste()
       << endl; //para ningun operador se pone el punto
  }
}
    
answered by 14.11.2018 в 07:37