C ++ 'da <=> operatörü nedir?


215

C ++ operatörleri hakkında bilgi edinmeye çalışırken , cppreference.com , * ' da garip bir karşılaştırma operatörü üzerine tökezledi :

resim açıklamasını buraya girin

"Peki, eğer bunlar C ++ 'da ortak operatörler ise, onları öğrensen iyi olur" diye düşündüm. Fakat bu gizemi açıklamaya yönelik tüm girişimlerim başarısız oldu. Burada bile Stack Overflow'da aramamda hiç şansım yoktu.

<=> ve C ++ arasında bir bağlantı var mı ?

Ve varsa, bu operatör tam olarak ne yapar?

* Bu arada cppreference.com bu sayfayı güncelledi ve şimdi <=>operatör hakkında bilgi içeriyor .


82
@haccks: Oh, lütfen, standarda oy bile verilmeyen şeyler hakkında birçok sorumuz vardı. Bir nedenden ötürü bir C ++ 20 etiketimiz var. Bu tür şeyler çok konuyla ilgili.
Nicol Bolas

1
@ cubuspl42 bar< foo::operator<=>bunun nasıl bir <--operatör gibi olabileceğine bir örnektir .
Yakk - Adam Nevraumont

8
@haccks: Doğru. C ++ 11 gibi C ++ 11'i uygulayan derleyiciler hakkında bir etikettir. Ve C ++ 14, C ++ 14'ü uygulayan derleyiciler hakkında bir etikettir. Ve C ++ 17, C ++ 17'yi uygulayan derleyicilerle ilgilidir. Hayır, C ++ 20, C ++ 20 hakkındaki bilgilerin etiketidir. Ve bu soru C ++ 20 ile ilgili olduğu için var. Yanlış olan etiket wiki'si, etiketin kendisi değil.
Nicol Bolas

Yanıtlar:


180

Buna üç yönlü karşılaştırma operatörü denir .

P0515 bildirisine göre :

Yeni bir üç yönlü karşılaştırma operatörü var <=>. İfade a <=> bkarşılaştıran bir nesne döndürür <0ise a < b, karşılaştırır >0eğer a > bve karşılaştırır ==0eğer ave beşit / eşdeğerdir.

Türünüzle ilgili tüm karşılaştırmaları yazmak için operator<=>, uygun kategori türünü döndüren yazmanız yeterlidir :

  • Dönüş bir _ordering senin tipin doğal destekliyorsa <ve biz verimli elde edersiniz <, >, <=, >=, ==, ve !=; aksi takdirde bir _ eşitliği döndürdüğünüzde etkin bir şekilde == ve ! = oluştururuz .

  • Eğer türünüz için a == bima ederse f(a) == f(b)(f, yalnızca özel olmayan arabirim kullanılarak erişilebilen karşılaştırma-çıkıntılı durumu okursa, ikame edilebilirlik), aksi takdirde zayıf dönün.

Cppreference diyor ki:

Üç yönlü karşılaştırma operatörü ifadeleri şu şekildedir:

lhs <=> rhs   (1)  

İfade,

  • karşılaştırır <0eğerlhs < rhs
  • karşılaştırır >0eğerlhs > rhs
  • ve karşılaştırır ==0eğer lhsve rhseşit / eşdeğerdir.

93
"Karşılaştırdığı <0", "karşılaştırdığı >0" ve "karşılaştırdığı ==0" ifadelerinin ne olduğu konusunda kafanız karışan (benim gibi) <=>, argümanlara bağlı olarak geri dönüşleri negatif, pozitif veya sıfır değeri anlamına gelir . Çok gibi strncmpve memcmp.
Cornstalks

1
@ Dai ikisi de olsa 'a' < 'a've 'c' < 'a'her ikisi de yanlış 'a' < 'a've 'a' < 'c'değildir. IN güçlü sipariş aşağıdaki doğrudur: a != ba < b || b < a
Revolver_Ocelot

1
@Revolver_Ocelot Ah, böylece operator==(T x, T y) { return !(x < y) && !(y < x); }ve operator!=(T x, T y) { return (x < y) || (y < x); }- ah-ha olarak tanımlanabilir / oluşturulabilir ! Elbette bu, ==karşılaştırmayı iki kez çağırdığı için gerçekten daha az etkilidir , ancak yine de temizdir.
Dai

3
"Güçlü dönüş" ve "zayıf dönüş" ne anlama geliyor?
lucidbrot

2
@hkBattousai, bu, < 0doğru olarak değerlendirildiğinde , nesnenin geri döndüğü anlamına gelir . Yani, eğer a < bo (a <=> b) < 0zaman her zaman doğrudur.
rmobis

116

On 2017-11-11 ISO C ++ komitesi kabul Herb Sutter için önerisini <=> 'uzay gemisi' üç yönlü karşılaştırma operatörü eklendi yeni özelliklerinden biri olarak 20 C ++ . Kağıt başlıklı yılında Tutarlı karşılaştırma Sutter, Maurer ve Kahverengi yeni tasarım kavramlarını göstermektedir. Teklife genel bir bakış için makaleden bir alıntı:

Sentezleme b <=> getirileri karşılaştırır bir amacı <0 ise <b , karşılaştırır > 0 ise , bir> b ve karşılaştırır == 0 a ve b, aynı / eşit ise.

Yaygın durum: X türünüzle ilgili tüm karşılaştırmaları Y türüyle , üye semantiklerle yazmak için şunu yazın:

auto X::operator<=>(const Y&) =default;

Gelişmiş vaka: senin tipin tüm karşılaştırmaları yazmak için X tipi ile Y sadece yazma, operatör <=> bir alan Y kullanabilirsiniz = varsayılan istenirse memberwise anlambilim almak ve döner uygun kategori türü:

  • Bir İade _ordering senin tipin doğal destekliyorsa < ve biz verimli simetrik elde edersiniz < , > , <= , > = , == ve ! = ; aksi takdirde _ eşitliği döndürdüğünüzde etkin bir şekilde simetrik == ve ! = üreteceğiz .
  • İade strong_ senin tipin için eğer a == b ima f (a) == f (b) (ikame edilebilirlik, f kamu kullanılarak erişilebilen tek karşılaştırma-belirgin halini okur const üye), aksi dönmek weak_ .

Karşılaştırma Kategorileri

Beş karşılaştırma kategorisi std::, her biri aşağıdaki önceden tanımlanmış değerlere sahip olan türler olarak tanımlanır:

+--------------------------------------------------------------------+
|                  |          Numeric  values          | Non-numeric |
|     Category     +-----------------------------------+             |
|                  | -1   | 0          | +1            |   values    |
+------------------+------+------------+---------------+-------------+
| strong_ordering  | less | equal      | greater       |             |
| weak_ordering    | less | equivalent | greater       |             |
| partial_ordering | less | equivalent | greater       | unordered   |
| strong_equality  |      | equal      | nonequal      |             |
| weak_equality    |      | equivalent | nonequivalent |             |
+------------------+------+------------+---------------+-------------+

Bu türler arasındaki örtük dönüşümler aşağıdaki gibi tanımlanır:

  • strong_orderingdeğerlerle { less, equal, greater} örtülü dönüşür:
    • weak_orderingdeğerlerle { less, equivalent, greater}
    • partial_orderingdeğerlerle { less, equivalent, greater}
    • strong_equalitydeğerlerle { unequal, equal, unequal}
    • weak_equalitydeğerlerle { nonequivalent, equivalent, nonequivalent}
  • weak_orderingdeğerlerle { less, equivalent, greater} örtülü dönüşür:
    • partial_orderingdeğerlerle { less, equivalent, greater}
    • weak_equalitydeğerlerle { nonequivalent, equivalent, nonequivalent}
  • partial_orderingdeğerlerle { less, equivalent, greater, unordered} örtülü dönüşür:
    • weak_equalitydeğerlerle { nonequivalent, equivalent, nonequivalent, nonequivalent}
  • strong_equalitydeğerlerle { equal, unequal} dolaylı olarak şuna dönüştürülür:
    • weak_equalitydeğerlerle { equivalent, nonequivalent}

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

<=>Belirteci ilave edilir. Karakter dizisi eski kaynak kodunda <=>tokenlenir <= >. Örneğin, X<&Y::operator<=>anlamını korumak için bir boşluk eklemesi gerekir.

Yüklenebilir operatör <=>üç yönlü bir karşılaştırma işlevidir ve önceliği daha yüksek <ve daha düşüktür <<. Değişmez değerlerle karşılaştırılabilecek bir tür döndürür, 0ancak ifade şablonlarını destekleme gibi diğer döndürme türlerine izin verilir. <=>Dilde ve standart kütüphanede tanımlanan tüm işleçler, yukarıda belirtilen 5 std::karşılaştırma kategorisi türünden birini döndürür .

Dil türleri için aşağıdaki yerleşik <=>aynı tür karşılaştırmalar sağlanır. Aksi belirtilmedikçe, hepsi sınırlıdır . Bu karşılaştırmalar skaler promosyonlar / dönüşümler kullanılarak heterojen olarak başlatılamaz.

  • İçin bool, integral ve işaretçi türleri, <=>geri dönüş strong_ordering.
  • İşaretçi türleri için, farklı cv-nitelikleri ve türetilmiş-baz dönüşümlerinin homojen bir yerleşik çağrılmasına izin verilir <=>ve yerleşik heterojen vardır operator<=>(T*, nullptr_t). Sadece aynı nesneye / tahsise işaretçilerin karşılaştırılması sabit ifadelerdir.
  • Temel kayan nokta türleri için, <=>döndürür partial_orderingve daha büyük bir kayan nokta türüne argümanlar genişletilerek heterojen olarak çağrılabilir.
  • Numaralandırmalar <=>için numaralandırmanın altında yatan türle aynı döndürür <=>.
  • Çünkü nullptr_t, <=>geri döner strong_orderingve daima verim verir equal.
  • Kopyalanabilir diziler için, 's ile T[N] <=> T[N]aynı türü döndürür ve lexicographic elementwise karşılaştırması yapar. Başka diziler için de yok .T<=><=>
  • Çünkü voidyok <=>.

Bu operatörün iç işleyişini daha iyi anlamak için lütfen orijinal belgeyi okuyun . Bu sadece arama motorlarını kullanarak öğrendim.


1
Sanki cpp yeterince karmaşık değildi. Neden sadece bir karşılaştırma yöntemi yazmıyorsunuz ...
Leandro

6
Uzay operatör @Leandro olan bu karşılaştırma yöntemi. Buna ek olarak, Just Çalışır ve diğer altı karşılaştırma operatörünü yazar (veya yazar). Altı ayrı kazan plakası üzerine yazılmış bir karşılaştırma operatörü işlevi alacağım.
anonim

O Not _equalitybunu ortaya çıktı: tipleri öldü <=>oynar de dört ilişkisel operatörler değil de iki eşitlik operatörleri (her ne kadar hepsini istiyorum ortak davasını desteklemek için bazı yoğun sözdizimsel şeker alınmamaktadır).
Davis Herring

12

Atıfta bulunulan web sayfası değiştiği için bu yanıt önemsiz hale geldi

Söz ettiğiniz web sayfası kırıldı. O gün çok fazla düzenleniyordu ve farklı bölümler senkronize değildi. Ben bakarken durumu:

Sayfanın en üstünde, şu anda var olan karşılaştırma işleçlerini listeler (C ++ 14'te). Orada yok <=>.

Sayfanın alt kısmında, aynı operatörleri listelemiş olmalılar, ancak ileride bu öneriyi eklediler.

gcc<=>henüz (ve -std=c++14asla, asla olmayacak) hakkında bilmiyor , bu yüzden demek istediğini düşünüyor a <= > b. Bu hata mesajını açıklar.

Aynı şeyi beş yıl sonra denerseniz muhtemelen daha iyi bir hata mesajı alırsınız, <=> not part of C++14.


1
OP'nin bağlantı verdiği web sayfası, bağlandığınız ayrı sayfa gibi doğrudur. Bu nitelendirir <=>bunu beklemek standart sürümünü söylüyorum, (20 C ++ beri) etiketle operatörü. Standartlar etiketleme cppreference.com izler bir gelenektir. Tabii ki, sizin için desteklemek için bir zaman makinesinde geri gelen bir derleyiciniz yok, ancak cpprefernce size (doğru) ne bekleyeceğinizi söylüyor.
Spencer

Evet, ama ... Cevap değil. Yorum yapıyorsun ... falan.
qlp

2
Soru ile aynı web sayfasına bağlantı vermeyi amaçladım, ancak özledim. Sorunun diğer cevapların vermediği kısımlarına cevap verdiğimi düşünüyorum. Diğer cesur soruları yanıtladığı için ana cesur soruyu görmezden geldim.
Stig Hemmer
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.