Знаете ли историята за момчето, което не каза нито дума, докато не беше на 10 години? Новият оператор за трипосочно сравнение ‹=›, представен в стандарта C++20, прилича малко на това малко момче — и ако това въведение няма никакъв смисъл, за много разработчици на C++ нито новият ‹=› оператор. В тази поредица от две статии ще разгадая и обясня всичко, което трябва да знаете за новия оператор ‹=›, известен още като оператор на космически кораб, за да можете да сравнявате с лекота.

Знаете ли историята за момчето, което не каза нито дума, докато не беше на 10 години? Родителите му го заведоха при най-добрите експерти: логопеди, експерти по детско развитие, лекари и психолози - нищо не помогна. Момчето не каза нито дума и никой, дори и най-добрият специалист, не можа да обясни защо. Докато един ден майката на момчето му сервира горещ шоколад. „Твърде горещо е!“, каза момчето. „Добри ми господарю! Можеш да говориш!“, извика майката, бършейки сълзите на радост, „защо не каза нищо досега?“, попита тя момчето. „Досега всичко беше наред“, отговорило момчето…

Точно като историята на малкото момче, всичко беше наред с операторите за сравнение на C++, които бяха наследени от C. Операторите и методите за сравнение останаха недокоснати години наред и техните роли бяха ясни, заедно с ясен набор от правила за това как да ги използвате .

Докато един ден нещо вече не беше наред и имаше нужда от нов метод, който може да поддържа тристранно сравнение между обекти. Ето как операторът за тристранно сравнение ‹=›, известен също като оператор на космически кораб, оживя като част от новия стандарт C++20.

Но какво липсваше? Наистина ли се нуждаем от друг начин за сравняване на обекти? Какво изобщо е трипосочно сравнение? И ако всичко беше наред години наред, защо внезапната промяна?

За да отговорим на всички тези въпроси, първо трябва да разгледаме как се правеха нещата в C++ до този момент.

По-добре, дяволът, когото познавате?

В програмирането, когато трябва да сравним два елемента, обикновено се нуждаем от булева стойност (да/не):

Едното е по-голямо/по-малко/равно/несравнимо с друго.

И така, потокът ще бъде: е A ‹ B и въз основа на резултата проверката е A › B. Ако никоя от тези опции не е вярна, можем да кажем, че A == B, но това би било извън обхвата на нашата заявка, тъй като нашата заявка връща само „true“ или „false“. Заключението е, че имаме нужда от две заявки, за да проверим три възможни резултата. Фигура 2 илюстрира потока от сравнение на два операнда, както би работило преди C++20.

Съвсем новото, трипосочно сравнение ‹=›, известно още като оператор на космически кораб поради подобната му форма на космически кораб, беше въведено в новия стандарт C++20 . Този оператор може да върне резултата от три сравнения, които са били претоварени към него: по-малко от оператора '', равно на оператора '= =' и операторът по-голямо от '›', който, комбиниран, конструира това: ‹=›.

Ако вече знаете малко за C++, може би знаете, че преди въвеждането на оператора космически кораб, програмистът понякога е използвал функциите memcmp() и strcmp(), които са били наследени от дните на C. Основният string::compare()който беше част от съвременния C++ беше (и все още е) също опция за сравнение. Тези функции са в състояние да осигурят един от три резултата при сравняване между два низа и ще върнат цяло число, за да посочат положителни или отрицателни стойности. Въпреки че тези методи са малко объркани и сложни, до оператора за трипосочно сравнение, те бяха буквално единственият начин за провеждане на този тип сравнения - и ето вашата причина за раждането на ‹=› оператор.

Операторът на космически кораб - това не е ракетна наука

За много разработчици на C++ и особено за тези, които са нови за C++, операторът за трипосочно сравнение е донякъде объркващ на пръв поглед. Много разработчици се борят да разберат откъде е „кацнал“ този космически кораб и защо е бил необходим на първо място, особено след като досега, точно както в историята на малките момчета, всичко изглеждаше наред. В този раздел обясняваме какво точно прави оператора на космически кораб по-добър и защо е необходим. Имайте предвид обаче, че обясненията в този раздел са частични и се отнасят само до това какво представлява тристранното сравнение, заедно с основната му логика. Ние не учим как всъщност да използвате този оператор във вашия код в този раздел.

В глави 3 и 6 на нашата книга Learning C++, написана от Michael Haephrati и Ruth Haephrati, публикувана от Manning Publications, ние се потапяме по-дълбоко в действителните свойства на тази концепция и как да я използваме във вашия код на доверие.

И така, какво е операторът за сравнение? Нека отново да погледнем фигура 2: можете да видите, че използвайки обикновените оператори, ние задаваме един въпрос. Например A‹ е отколкото B? Въпреки че имаме три възможни изхода, ние получаваме само два възможни изхода от трите. Това означава, че трябва да направим друго запитване. Да видим какво трябва да попитаме в този случай:

Въпрос 1: A по-голямо ли е от B?

След това въз основа на отговора задавате втория въпрос:

Въпрос 2: A равно ли е на B?

Новият оператор на космически кораб ни позволява да извършваме същата компресия с единствена заявка. Можем да го използваме винаги, когато стойностите се сравняват с помощта на ‹, ›, ‹=, ›=. Това е като да излезете на среща на сляпо и да попитате: „Кажи ми всичко, което трябва да знам за теб...“

Тристранното сравнение ви позволява да получите вашите отговори по отношение на въпроса: „какво можете да ми кажете за връзката между А и Б.“

С тристранната компресия задавате само един въпрос и получавате един от трите резултата:

A > B

B > A

A == B

Фигура 3 илюстрира основната логика зад тристранното сравнение. Както можете да видите, в случай A‹B функцията за трипосочно сравнение ще върне число, по-малко от 0. В случай A=B функцията за трипосочно сравнение ще върне число, равно на 0, а в случай A›B функцията ще върне число › различно от 0.

Огромната стойност на този нов оператор, освен ултра-готиния псевдоним, е фактът, че с помощта му ние консолидираме пълния набор от три условия в една единствена нахална заявка. Методологията за тристранно сравнение се нарича още трихотомия — разделяне на три категории. Не винаги е необходимо да използваме трихотомия в нашия код, но когато го правим, операторът на космическия кораб е много удобен и може да опрости нашия код много. Тъй като кодът е по-силен от думите, нека разгледаме двата кодови фрагмента по-долу.

ПРИМЕРА 1:
A ‹= B && B ‹= A

В тази извадка ние питаме: A по-малко ли е или равно на B и дали B е по-малко или равно на A?

ПРОМЕР 2:
! (A ‹ B) && ! (B ‹ A)

В този пример ние питаме: A не е ли по-малко от B и дали B не е по-малко от A?

Сега можем да консолидираме цялата тази бъркотия в малко чисто изявление:

A <=> B

Колко готино е това!

Практическо използване на тристранното сравнение

Въпреки че в тази статия използваме прости примери, за да опростим обяснението на сложна концепция, вероятно можете да се досетите, че в реалния код няма да използваме ‹=› за сравняване на прости обекти или цели числа. Логиката зад добавянето на оператора за трипосочно сравнение към C++20 беше да се опрости сравнението между сложни типове, като низове, списъци, последователности и контейнери – и стигаме до това във втората част на тази статия.

В следващата статия ще се потопим по-дълбоко в оператора за космически кораб и ще научим как да го използваме в нашия код с помощта на метод, който може да замени memcmp(), strcmp() и compare().

C++ е сериозен език за програмиране за важен софтуер и е един от най-добрите езици за програмиране от 30 години — и не се забавя. Накъдето и да погледнете, пръстовите отпечатъци на C++ са навсякъде. Никога не е лош момент да го научите и моята нова книга, написана съвместно с Michael Haephrati и публикувана от Manning Publications, ще ви помогне да направите точно това — дори и да нямате опит в програмирането или компютърните науки.