20 Mart 2019 Çarşamba

Comparison Operators - Equal to

Giriş
İki nesnenin eşitliği için kullanılan metod imzasında her zaman const kullanmaya dikkat etmek lazım.
bool operator ==(const MyClass& u, const MyClass& v)
//               ^^^^^                 ^^^^^
// Note the use of `const`
Böylece temporary nesneler de kullanılabilir. Eğer yapmazsak aşağıdaki gibi unary minus operatörünün döndürdüğü temporary nesne için derleme hatası alırız.
MyClass u = {3.14,-2.56};
MyClass expected = {-u.vx,-u.vy};

if(expected_vec == (-u))    // Derleme hatası
Birden fazla alana göre kontrol
Birden fazla alana göre eşitliği kontrol etmek için std::tie kullanılabilir. Elimizde şöyle bir sınıf olsun.
struct Foo {
    A a;
    B b;
    C c;
    ...

private:
    auto tied() const { return std::tie(a, b, c, ...); }
};
eşittir öperatörü şöyle yazılabilir.
bool operator==(Foo const& rhs) const { return tied() == rhs.tied(); }
Kendi operatör metodumuzu da yazabilirdik.
struct Foo
{
  int a,b,c,d,e,f;
  bool operator==(const Foo& rhs) { 
   return std::tie(a,b,c,d,e,f) == std::tie(rhs.a,rhs.b,rhs.c,rhs.d,rhs.e,rhs.f); 
  }
};
Örnek
Kalıtım varsa operator==() metodu virtual bir metod çağırabilir. Şöyle yaparız
struct Identifier {    
  bool operator==(const Identifier& other) const {
    return isEqual(other); //Burada virtual metodu çağır
  }
private:
  virtual bool isEqual(const Identifier& other) const = 0;
};

// Note: do not derive this class further (less dyncasts may logically fail).
struct UserIdentifier final : public Identifier {
  int userId = 0;
private:
  virtual bool isEqual(const Identifier& other) const override {
    const UserIdentifier *otherUser = dynamic_cast<const UserIdentifier*>(&other);
    return otherUser && otherUser->userId == userId;
  }
};

// Note: do not derive this class further (less dyncasts may logically fail).
struct MachineIdentifier final : public Identifier {
  int machineId = 0;
private:
  virtual bool isEqual(const Identifier& other) const override {
   const MachineIdentifier *otherMachine = dynamic_cast<const MachineIdentifier*>(&other);
   return otherMachine && otherMachine->machineId == machineId;
  }
};
Örnek
Kendi yazdığımız == operator() metodu ile built-in == metodları çakışabilir. Açıklaması şöyle
In the case of a == b and c == d, the built-in candidate operator==(int, int) (see [over.built]/13) competes with the operator== defined as a member of Foo<T>.
Elimizde şöyle bir kod olsun.
template<class T>
class Foo
{
private:
  T m_value;

public:
  Foo();

  Foo(const T& value):
    m_value(value)
  {
  }

  operator T() const {
    return m_value;
  }

  bool operator==(const Foo<T>& other) const {
    return m_value == other.m_value;
  }
};

struct Bar
{
  bool m;

  bool operator==(const Bar& other) const {
    return false;
  }
};
Görmek için şöyle yaparız. Burada problem Foo sınıfının operator T() metoduna sahip olması. Derleyici Foo'yu bool'a çevirip mi karşılaştıracağını yoksa, Foo'nun operator==() metodunu mu çağıracağını bilemiyor.
Foo<bool> a (true);
bool b = false;
if(a == b) {
  // This is ambiguous
}

Foo<int> c (1);
int d = 2;
if(c == d) {
  // This is ambiguous
}

Foo<Bar> e (Bar{true});
Bar f = {false};
if(e == f) {
  // This is not ambiguous. Why?
}

Hiç yorum yok:

Yorum Gönder