How to mount the operator == of a struct?

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 CICLOs and store them in a set (because I need to bulk up I will not keep repeating 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 happens to add in Conjuncts, one or another repeated cycle. Debugging the code, I realized that the operator == defined for the struct ARCO_TEMPO, is not working.

When I change the comparison of two ARCOs_TEMPO in the operator < of the struct CYCLE:

if (*itobj1 == *itobj2) {

by:

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 with setting my operator ==?

    
asked by anonymous 07.04.2018 / 23:12

1 answer

0

You return true when 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 objects are different. Instead, it allows the stream 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 does not hurt anyone ...

If you allow me a little addendum: Some features introduced in the 2011 version of C ++ ( C++11 ) would make your life a lot easier, and your compiler is probably already configured 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";
        });
}

Output:

Igual
Diferente
Diferente
Diferente
Diferente

Watch live!

    
26.05.2018 / 16:53