C++ programlama dili: Otomatik olarak oluşturulan eşitlik operatörü

Adanali

Active member
C++ programlama dili: Otomatik olarak oluşturulan eşitlik operatörü


  1. C++ programlama dili: Otomatik olarak oluşturulan eşitlik operatörü

Çoğu C++ geliştiricisi, üç yönlü karşılaştırma operatörünü tanımlamaya veya kullanmaya aşina olacaktır. =default derleyici tarafından gerekli olabilir. Muhtemelen daha az bilinen şey, eşitlik operatörünün C++ 20'de de tanımlanabileceği veya gerekli olabileceğidir?

Duyuru









Otomatik olarak oluşturulan eşitlik operatörünü tartışmadan önce, üç yönlü karşılaştırma operatörü hakkındaki temel gerçekleri tazelemek istiyorum.







Rainer Grimm uzun yıllardır yazılım mimarı, ekip ve eğitim yöneticisi olarak çalışmaktadır. C++, Python ve Haskell programlama dilleri üzerine makaleler yazmaktan hoşlanıyor, aynı zamanda özel konferanslarda sık sık konuşmaktan da hoşlanıyor. Modern C++ adlı blogunda C++ tutkusunu yoğun bir şekilde ele alıyor.







Üç yönlü karşılaştırma operatörü


Üç yönlü karşılaştırma operatörü veya ile tanımlanabilir. =default derleyici isteği. Her iki durumda da altı karşılaştırma operatörünün tümünü elde edersiniz: ==, !=, <, <=, >, VE >=.


// threeWayComparison.cpp&#13;
&#13;
#include <compare>&#13;
#include <iostream>&#13;
&#13;
struct MyInt {&#13;
int value;&#13;
explicit MyInt(int val): value{val} { }&#13;
auto operator<=>(const MyInt& rhs) const { // (1) &#13;
return value <=> rhs.value;&#13;
}&#13;
};&#13;
&#13;
struct MyDouble {&#13;
double value;&#13;
explicit constexpr MyDouble(double val): value{val} { }&#13;
auto operator<=>(const MyDouble&) const = default; // (2)&#13;
};&#13;
&#13;
template <typename T>&#13;
constexpr bool isLessThan(const T& lhs, const T& rhs) {&#13;
return lhs < rhs;&#13;
}&#13;
&#13;
int main() {&#13;
&#13;
std::cout << std::boolalpha << std::endl;&#13;
&#13;
MyInt myInt1(2011);&#13;
MyInt myInt2(2014);&#13;
&#13;
std::cout << "isLessThan(myInt1, myInt2): "&#13;
<< isLessThan(myInt1, myInt2) << std::endl;&#13;
&#13;
MyDouble myDouble1(2011);&#13;
MyDouble myDouble2(2014);&#13;
&#13;
std::cout << "isLessThan(myDouble1, myDouble2): "&#13;
<< isLessThan(myDouble1, myDouble2) << std::endl; &#13;
&#13;
std::cout << std::endl;&#13;
&#13;
}


Kullanıcı tanımlı (1) ve derleyici tarafından oluşturulan (2) üç yönlü karşılaştırma işleçleri beklendiği gibi çalışır.








Ancak iki üç yönlü karşılaştırma operatörü arasında bazı önemli farklılıklar vardır. Derleyici, dönüş türünü çıkardı MyInt (1) derleyicinin dönüş türünü çıkardığı katı sıralamayı destekler MyDouble Ancak (2) yalnızca kısmi sıralamayı destekler. Kayan noktalı sayılar yalnızca kısmi sıralamayı destekleyebilir çünkü NaN (Sayı Değil) gibi değerler sıralanamaz. Örneğin bu geçerlidir NaN == NaN İLE false değerli.

Örtülü olan, derleyici tarafından oluşturulan üç yollu karşılaştırma operatörü constexpr VE noexcept yani başlık gerektirir <compare>. Ayrıca sözlükbilimsel bir karşılaştırma yapın. Bu bağlamda sözlükbilimsel karşılaştırma, tüm temel sınıfların soldan sağa, tüm statik olmayan üyelerin ise bildirildikleri sıraya göre karşılaştırılması anlamına gelir.

Diyelim ki iki sınıfı ekledim MyInt VE MyDouble A std::unordered_set katma.


struct MyInt {&#13;
int value;&#13;
std::unordered_set<int> mySet;&#13;
explicit MyInt(int val): value{val}, mySet{val} { }&#13;
bool operator<=>(const MyInt& rhs) const {&#13;
if (auto first = value <=> rhs.value; first != 0) return first;&#13;
else return mySet <=> rhs.mySet; &#13;
}&#13;
};&#13;
&#13;
struct MyDouble {&#13;
double value;&#13;
std::unordered_set<double> mySet;&#13;
explicit MyDouble(double val): value{val}, mySet{val} { }&#13;
bool operator<=>(const MyDouble&) const = default; &#13;
};&#13;



Üç yönlü karşılaştırma isteği veya tanımı başarısız çünkü std::unordered_set hiçbir sipariş desteklenmiyor. std::unordered_set yalnızca eşitlik karşılaştırmalarını destekler ve bu aynı zamanda aşağıdakiler için de geçerlidir: MyInt VE MyDouble.

eşitlik operatörü


Eşitlik operatörü derleyici tarafından tanımlanır veya kullanılır =default gerekli olduğunda eşitlik ve eşitsizlik operatörleri otomatik olarak elde edilir: ==VE !=.


// equalityOperator.cpp&#13;
&#13;
#include <iostream>&#13;
#include <tuple>&#13;
#include <unordered_set>&#13;
&#13;
struct MyInt {&#13;
int value;&#13;
std::unordered_set<int> mySet;&#13;
explicit MyInt(int val): value{val}, mySet{val} { }&#13;
bool operator==(const MyInt& rhs) const { &#13;
return std::tie(value, mySet) == std::tie(rhs.value, rhs.mySet);&#13;
}&#13;
};&#13;
&#13;
struct MyDouble {&#13;
double value;&#13;
std::unordered_set<double> mySet;&#13;
explicit MyDouble(double val): value{val}, mySet{val} { }&#13;
bool operator==(const MyDouble&) const = default; &#13;
};&#13;
&#13;
template <typename T>&#13;
constexpr bool areEqual(const T& lhs, const T& rhs) {&#13;
&#13;
return lhs == rhs;&#13;
}&#13;
&#13;
template <typename T>&#13;
constexpr bool areNotEqual(const T& lhs, const T& rhs) {&#13;
&#13;
return lhs != rhs;&#13;
}&#13;
&#13;
int main() {&#13;
&#13;
std::cout << std::boolalpha << 'n';&#13;
&#13;
MyInt myInt1(2011);&#13;
MyInt myInt2(2014);&#13;
&#13;
std::cout << "areEqual(myInt1, myInt2): "&#13;
<< areEqual(myInt1, myInt2) << 'n';&#13;
std::cout << "areNotEqual(myInt1, myInt2): "&#13;
<< areNotEqual(myInt1, myInt2) << 'n';&#13;
&#13;
std::cout << 'n'; &#13;
&#13;
MyDouble myDouble1(2011.0);&#13;
MyDouble myDouble2(2014.0);&#13;
&#13;
std::cout << "areEqual(myDouble1, myDouble2): "&#13;
<< areEqual(myDouble1, myDouble2) << 'n';&#13;
std::cout << "areNotEqual(myDouble1, myDouble2): "&#13;
<< areNotEqual(myDouble1, myDouble2) << 'n'; &#13;
&#13;
std::cout << 'n';&#13;
&#13;
}


Şimdi yapabilirim MyInt VE MyDouble Eşitlik ve eşitsizliği karşılaştırın.

Programda equalityOperator.cpp Bir numara kullandım: Bunu kim tanıyacak?

Aşağıdaki örnekte eşitlik operatörüne sahibim: MyInt eşitlik operatörleri kullanılarak uygulanır value VE mySet zincirlenmiş.


struct MyInt {&#13;
int value;&#13;
std::unordered_set<int> mySet;&#13;
explicit MyInt(int val): value{val}, mySet{val} { }&#13;
bool operator==(const MyInt& rhs) const {&#13;
if (auto first = value == rhs.value; first != 0) return first;&#13;
else return mySet == rhs.mySet; &#13;
}&#13;
};


Bu oldukça hataya açıktır ve birden fazla üyesi olan bir sınıfınız varsa çirkin görünür.

Tam tersine bende var std::tie programda eşitlik operatörünü kullandık equalityOperator.cpp uygulamak.


struct MyInt {&#13;
int value;&#13;
std::unordered_set<int> mySet;&#13;
explicit MyInt(int val): value{val}, mySet{val} { }&#13;
bool operator==(const MyInt& rhs) const { &#13;
return std::tie(value, mySet) == std::tie(rhs.value, rhs.mySet);&#13;
}&#13;
};&#13;



std::tie bir demet oluşturur lvalue-Argümanlarına yapılan atıflar. Son olarak oluşturulan demetler sözlükbilimsel olarak karşılaştırılmıştır.

Sıradaki ne?


Bir sonraki yazımda C++20 ve ötesi yolculuğuma devam edeceğim std::span yazmak. std::span bağlantılı bir nesne dizisine atıfta bulunan bir nesneyi temsil eder.


(harita)



Haberin Sonu
 
Üst