How to mount Operator == from a struct?

Asked

Viewed 161 times

0

I have the following structs:

struct Arco {

  int i, j;
  Arco () {};
  Arco (const Arco& obj): i(obj.i), j(obj.j) {};
  Arco(int _i, int _j) : i(_i), j(_j) {}    

};

struct ARCO_TEMPO {
  Arco a;
  int slotTimeU; 
  int slotTimeV; 
  ARCO_TEMPO () {};
  ARCO_TEMPO (const ARCO_TEMPO& obj): a(obj.a), slotTimeU(obj.slotTimeU),     slotTimeV(obj.slotTimeV) {};
  ARCO_TEMPO (Arco _a, int _slotTimeU, int _slotTimeV, int _order) : a(_a), slotTimeU(_slotTimeU), slotTimeV(_slotTimeV) {}    

};


struct CICLO {
  vector<ARCO_TEMPO> arco_tempo;
  set<ARCO_TEMPO> arco_tempo_order;
  set<int> arco_tempo_Aux;
  int aircraftType; 
  float COST;
};

Throughout my algorithm, I create Cycles and save them on a set (because I need granatir that will not keep repeated cycles).

I then defined the following Operators:

bool operator<(const ARCO_TEMPO& obj1, const ARCO_TEMPO& obj2) {
  if (obj1.slotTimeU < obj2.slotTimeU) {
    return true;
  }
  else {
    if (obj1.slotTimeU == obj2.slotTimeU && obj1.slotTimeV < obj2.slotTimeV) {
      return true;
    }
    else {
      if (obj1.slotTimeU == obj2.slotTimeU && obj1.slotTimeV == obj2.slotTimeV && obj1.a.i < obj2.a.i) {
        return true;
      }
      else {
        if (obj1.slotTimeU == obj2.slotTimeU && obj1.slotTimeV == obj2.slotTimeV &&obj1.a.i == obj2.a.i && obj1.a.j < obj2.a.j ) {
          return true;
        }
        else{ 
          return false;
        }
      }
    }
  }
}

bool operator==(const ARCO_TEMPO& obj1, const ARCO_TEMPO& obj2) {
  if (obj1.slotTimeU == obj2.slotTimeU && obj1.slotTimeV == obj2.slotTimeV &&obj1.a.i == obj2.a.i && obj1.a.j == obj2.a.j ) {
    return true;
  }
}

bool operator<(const CICLO& obj1, const CICLO& obj2) {

  if (obj1.COST < obj2.COST - 1) {
    return true;
  }
  else {
    if ( (abs(obj1.COST - obj2.COST) < 1) && obj1.aircraftType < obj2.aircraftType) {
      return true;
    }
    else {
      if (obj1.aircraftType == obj2.aircraftType && (abs(obj1.COST - obj2.COST) < 1) && obj1.arco_tempo_order.size() < obj2.arco_tempo_order.size()) {
          return true;
      }
      else {
        if (obj1.aircraftType == obj2.aircraftType && (abs(obj1.COST - obj2.COST) < 1) && obj1.arco_tempo_order.size() == obj2.arco_tempo_order.size()) {
          bool igual = true;
          set<ARCO_TEMPO>::iterator itobj1;
          set<ARCO_TEMPO>::iterator itobj2;
          for (itobj1 = obj1.arco_tempo_order.begin(), itobj2 = obj2.arco_tempo_order.begin();  itobj1 != obj1.arco_tempo_order.end(); itobj1++,itobj2++) {
            if (igual && *itobj1 < *itobj2) {
              return true;
            } 
            else {
              if (*itobj1 == *itobj2) {
                igual = true;
              }
              else {
                return false;
              }
            }
          }
          return false;
        }
        else{ 
          return false;
        }
      }
    }
  }
}

// estrutura que guarda os ciclos criados
set<CICLO> ConjCiclos;

//crio um ciclo
CICLO cc;
// preencho esse ciclo ...

// antes de adiciona o ciclo verifico se e ele ja nao foi adicionado através da função:

bool is_CycleIT_a_new_one(CICLO &it, set<CICLO> &ConjCiclos) {

  return ConjCiclos.count(it) == 0; 

}

However, it occurs to add in Conjciclos, one or another cycle repeated. Debugging the code, I realized that the Operator == set to the struct ARCO_TEMPO, is not working.

When I change the comparison of two Arcs_tempo in the CYCLE struct:

if (*itobj1 == *itobj2) {

for:

if (itobj1->a.i == itobj2->a.i && itobj1->a.j == itobj2->a.j && itobj1->slotTimeU == itobj2->slotTimeU && itobj1->slotTimeV == itobj2->slotTimeV) {

the algorithm works ok, without adding repeated cycles.

Can anyone tell me what is wrong in the definition of my Operator==?

1 answer

0

You return true when the objects are equal...

bool operator==(const ARCO_TEMPO& obj1, const ARCO_TEMPO& obj2) {
  if (obj1.slotTimeU == obj2.slotTimeU && obj1.slotTimeV == obj2.slotTimeV &&obj1.a.i == obj2.a.i && obj1.a.j == obj2.a.j ) {
    return true; // OK
  }
}

...but never returns false when the objects are different. Instead, it allows the flow to reach the end of the function without returning any value. According to the C++ standard, the behavior in this case is undefined.

To correct, just return false when the objects are different:

bool operator==(const ARCO_TEMPO& obj1, const ARCO_TEMPO& obj2) {
  if (obj1.slotTimeU == obj2.slotTimeU && obj1.slotTimeV == obj2.slotTimeV &&obj1.a.i == obj2.a.i && obj1.a.j == obj2.a.j ) {
    return true;
  } else {
    return false;
  }
}

Or more concisely:

bool operator==(const ARCO_TEMPO& obj1, const ARCO_TEMPO& obj2) {
   return obj1.slotTimeU == obj2.slotTimeU && obj1.slotTimeV == obj2.slotTimeV &&obj1.a.i == obj2.a.i && obj1.a.j == obj2.a.j
}

A little extra knowledge never hurt anyone...

If I may make a small addendum: Some Features introduced in 2011 version of C++ (C++11) make your life a lot easier, and your compiler is probably already set up to use them.

#include <algorithm>
#include <iostream>
#include <iterator>

struct Arco {
  int i, j;

  bool operator==(const Arco& rhs) {return i == rhs.i && j == rhs.j;}
};

struct ARCO_TEMPO {
  Arco a;
  int slotTimeU; 
  int slotTimeV;
  // Para structs triviais, não há a necessidade de criar construtores.
  // Bastar usar listas de inicialização (Com chaves ao invés de parênteses)

  bool operator==(const ARCO_TEMPO& rhs) {return slotTimeU == rhs.slotTimeU && slotTimeV == rhs.slotTimeV && a == rhs.a;}
};

int main() {
    // O compilador é esperto o suficiente para inicializar as structs
    // conforme a ordem dos elementos. (E ainda inicializa structs aninhadas!)
    ARCO_TEMPO t{{1,1}, 1, 1};
    ARCO_TEMPO a[] {
        {{1,1}, 1, 1}, // Igual
        {{1,1}, 1, 0}, // Diferente
        {{1,1}, 0, 1}, // Diferente
        {{1,0}, 1, 1}, // Diferente
        {{0,1}, 1, 1}  // Diferente
    };

    // Para cada item do vetor, imprime "Igual" se o item for igual a 't',
    // ou "Diferente" se o item for diferente de 't'.
    std::transform(std::begin(a), std::end(a),
        std::ostream_iterator<std::string>(std::cout), 
        [&t](const ARCO_TEMPO& i) {
            return t==i?"Igual\n":"Diferente\n";
        });
}

Exit:

Igual
Diferente
Diferente
Diferente
Diferente

Watch live!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.