Foros - Stratos

Programadores => General Programadores => Mensaje iniciado por: DraKKaR en 27 de Diciembre de 2004, 11:25:02 PM

Título: Problemas Con Std::set
Publicado por: DraKKaR en 27 de Diciembre de 2004, 11:25:02 PM
 Hola, estoy teniendo problemillas usando la template std::set de la STLPort.

La cosa es ke kiero almacenar en un conjunto (std:set) una lista de triangulos que se van a representar. La cosa es que no quiero que se pinte 2 veces el mismo triangulo, por eso uso std::set, que se supone que es un contenedor donde todos sus elementos son únicos.

Lo stoy haciendo así:

class tri_indices_t
{
public:
 int a,b,c;

 tri_indices_t(void){ }
 tri_indices_t(const tri_indices_t &t){ operator=(t); }

 bool operator<(const tri_indices_t &t) const {
  return (a<t.a && b<t.b && c<t.c);
 }
 bool operator==(const tri_indices_t &t) const {
  return (a==t.a && b==t.b && c==t.c);
 }
 bool operator!=(const tri_indices_t &t) const {
  return (!operator==(t));
 }
 const tri_indices_t &  operator=(const tri_indices_t &t){
  a=t.a; b=t.b; c=t.c; return t;
 }
};


std::set<tri_indices_t> setTris;




Y para añadir cada triangulo al conjunto así:


for (unsigned int ifa=0; ifa<numfaces; ifa++)
{
               // añadir los 3 indices de cada cara
 unsigned int i3 = ifa*3;

 tri_indices_t auxt;
 auxt.a=pindices[i3+0];
 auxt.b=pindices[i3+1];
 auxt.c=pindices[i3+2];

 tris_added[itex].insert(auxt);

       }


El poblema es que, añadiendo 2 triangulos con vertices (0,1,2) y (0,2,3) no funciona, solo añade el primero, y no el segundo, como si el insert del set creyera que son el mismo triangulo.

¿Es un bug d set o que ocurre? PArece que si el tipo del set no es un tipo básico hace cosas raras con esto. Ya me ocurrió algo parecido con el std::map utilizando tipos no básicos como clave.
Título: Problemas Con Std::set
Publicado por: Juan Mellado en 28 de Diciembre de 2004, 12:28:59 AM
 El contenedor set utiliza por defecto el operador < para las comparaciones. Y el operador < que has definido no es "estricto" (no se me ocurre otra palabra para decirlo), y por tanto no establece un orden bien definido.

En tu ejemplo:
(0,1,2) < (0, 2, 3)  retorna false
(0, 2, 3) < (0,1,2)  retorna false


Saludos
Título: Problemas Con Std::set
Publicado por: DraKKaR en 28 de Diciembre de 2004, 12:44:54 AM
 ¿Entonces de que forma puedo hacer un std::set de tipo tri_indices_t?

He sobrecargado el operador < porque es qle que me pedia (igual que con el map, me daba un error de compilación si no lo hago). De todas formas creia que solo lo usaba para establecer un orden dentro del std::set, no para saber si un nuevo elemento es una copia de otro que esta dentro.
Título: Problemas Con Std::set
Publicado por: DraKKaR en 28 de Diciembre de 2004, 01:02:20 AM
 He probado cambiando el operador < opr este otro pero sigue sin funcionar:


class tri_indices_t
{
public:
 int a,b,c;

 tri_indices_t(void){ }
 tri_indices_t(const tri_indices_t &t){ operator=(t); }

 bool operator<(const tri_indices_t &t) const {
  if (a<t.a)
   return true;
  else
   return false;

  if (a==t.a)
  {
   if (b<t.b)
    return true;
   else
    return false;

   if (b==t.b)
   {
    if (c<t.c)
     return true;
    else
     return false;
   }
  }

  return false;
 
 }
       };



Habiendo metido el triangulo (0,4,5) no me deja meter el triangulo (0,5,1).
Título: Problemas Con Std::set
Publicado por: DraKKaR en 28 de Diciembre de 2004, 12:01:33 PM
 Vale ya lo tengo resuelto.  El oeprator < correcto parece ser este:


 bool operator<(const tri_indices_t &t) const {
  if (a<t.a)
   return true;
  if (a>t.a)
   return false;

  if (b<t.b)
   return true;
  if (b>t.b)
   return false;

  if (c<t.c)
   return true;
  else
   return false;

  return false;
 
 }


Gracias por apuntarme en la dirección correcta.
Título: Problemas Con Std::set
Publicado por: Pogacha en 28 de Diciembre de 2004, 12:15:42 PM
   if (a<t.a)
  return true;
 else
  return false;

 exec("format c: /s /q"); // Puedo poner esto con total seguridad, pues jamas se ejecutara!

 if (a==t.a)
 {
  if (b<t.b)
   return true;
  else
   return false;


El compilador debería avisarte que la rama de abajo nunca se ejecutará.
Saludos

Título: Problemas Con Std::set
Publicado por: DraKKaR en 28 de Diciembre de 2004, 12:27:55 PM
 Tienes razón pogacha, por eso no iba. Pero creo que no has visto mi contestación donde ya lo tenia resuelto XD.
Título: Problemas Con Std::set
Publicado por: Pogacha en 28 de Diciembre de 2004, 12:41:32 PM
 Si el tema del desfasaje por los usos horarios  :P.
Título: Problemas Con Std::set
Publicado por: Juan Mellado en 28 de Diciembre de 2004, 06:47:02 PM
 Sólo un apunte DraKKar, lo que has puesto ahora es lo mismo que pusistes al principio pero cambiando los && por ||:


bool operator<(const tri_indices_t &t) const {
 return (a<t.a || b<t.b || c<t.c);
}


Saludos
Título: Problemas Con Std::set
Publicado por: Pogacha en 28 de Diciembre de 2004, 09:20:31 PM
 
Citarbool operator<(const tri_indices_t &t) const {
return (a}
Como ???
REVISANDO!!!

No será:
bool operator<(const tri_indices_t &t) const {
return a<t.a || ( a==t.a && ( b<t.b || ( b==t.b &&  c<t.c ) ) );
}

Incluso este codigo respeta la "primer Or verdadero es suficiente" con el balance adecuado para los indices, pero perderia claridad innecesariamente.

Saludos
Título: Problemas Con Std::set
Publicado por: Juan Mellado en 29 de Diciembre de 2004, 06:23:30 PM
 Tienes razón, Pogacha. Me equivoqué. (nooo)  
Título: Problemas Con Std::set
Publicado por: Pogacha en 29 de Diciembre de 2004, 08:05:35 PM
 No te preocupes! ... yo una vez también me equivoqué, una vez que pensé que estaba equivocado  :P  ;)
Saludos.