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
}
}