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 != b→a < 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.