본문 바로가기
C++20/Language

[C++20 - Language] Chapter 01. Three-Way Comparison 연산자 (Spaceship Operator <=> )

by song.ift 2023. 7. 26.

GitHub :https://github.com/developeSHG/CPP20-Language/commit/f711b3b8cfbbd4f83d077c81743b4a034b47ba83 

 

Three-Way Comparison 연산자 (Spaceship Operator <=> ) · developeSHG/CPP20-Language@f711b3b

developeSHG committed Jul 27, 2023

github.com

 

 


 

 

// < <= > >= == !=
// 보통 < 로 연산자 오버로딩을 하면 위의 수식도 필요한게 일반적.
// 저것을 다 정의하는 것보다, 알아서 자동으로 해줄 수 있게 지원하는 게 Spaceship Operator <=>

 

// [여기서 이상한 점]
// <=> 연산자를 사용했지만
// 만약 value가 한 개가 아닌 여러개가 있다고 가정하면, 
// 오퍼레이터 연산자가 어떤 변수를 기준으로 했는지 만들어졌는지 모호하다. 
// 또 bool 타입으로 리턴을 안하고, string_ordering 이라는 타입이 무엇을 하는지 알 수가 없다.

// ordering 이라는 것이 크게 3가지로 구분할 수 있다.
// 1. strong ordering
// 2. weak ordering
// 3. partial ordering

// 위의 ordering들의 차이를 알기위해선 비교 특성에 대해 먼저 알고 있어야 한다.
// 비교 (Relational, Equivalence, Comparable)
// - 6종 비교 연산 지원 ==, !=, <, <=, >, >= (Relational 조건을 만족)
// - 모든 Equivalent한 값들은 서로 구분되지 않고 완전 똑같다 (Equivalence 조건을 만족)
// ex) 대소문자 구별 안하는 문자열 비교 abc Abc
// - a < b, a == b, a > b 중 하나는 참이다 (Comparable 조건을 만족)
// ex) float 비교할 때, b가 NaN(not a number)면 3연산이 다 true가 아님.

// Strong Ordering : Relational(O), Equivalence(O), Comparable(O)
// Weak Ordering : Relational(O), Comparable(O)
// Partial Ordering : Relational(O)

// weak ordering 같은 경우는 C++ 표준에서 사용하는 타입중에서 weak ordering으로 된 경우는 잘 없기 떄문에 직관적이지 않고,
// 보통 string ordering과 partial ordering이 친숙하고 직관적이다.

// 다시 위에서 이상한 점을 야기한대로
// 변수가 여러개 있다고 가정하면, 선언된 순서대로 하나씩 테스트해보게 된다.

cpp
닫기
#include <iostream> using namespace std; #include <list> #include <vector> #include <map> #include <algorithm> #include <ranges> #include <concepts> #include <coroutine> // 오늘의 주제 : Three-Way Comparison 연산자 (Spaceship Operator <=> ) struct MyInt { MyInt(int value) : _value(value) { } // < <= > >= == != // 보통 < 로 연산자 오버로딩을 하면 위의 수식도 필요한게 일반적. // 저것을 다 정의하는 것보다, 알아서 자동으로 해줄 수 있게 지원하는 게 Spaceship Operator bool operator<(const MyInt& rhs) const { return _value < rhs._value; } auto operator<=>(const MyInt& rhs) const = default; // 리턴형 타입을 bool로 하면 에러가 난다. 자동추론하게끔 // auto operator<=>(const MyInt& rhs) const { return _value <=> rhs._value; } // 어떤 식으로 이루어질지 정의해줄 수 있지만, 간단하게해서 컴파일이 알아서 만들어줄 수 있기에 default int _value; }; struct Strong { ‌std::strong_ordering operator<=>(const Strong&) const = default; }; struct Weak { ‌std::weak_ordering operator<=>(const Weak&) const = default; }; struct Partial { ‌std::partial_ordering operator<=>(const Partial&) const = default; }; struct Test { auto operator<=>(const Test&) const = default; // 위의 타입은 자동추론에 의해 partial_ordering 으로 되어있다. // 왜그러냐면 밑의 변수들의 타입 strong, weak, partial의 ordering 조건을 모두 만족해야 하는데, // 밑에 설명한대로 partial의 비교 조건이 제일 느슨하기 때문에 // strong은 weak, partial을 포함하고 있고, weak는 partial을 포함하고 있기에 // strong과 weak를 할 수 없는 제약사항이 있어서 partial_ordering으로 되었다. ‌Strong s; ‌Weak w; ‌Partial p; }; int main() { ‌{ ‌‌MyInt a = 1; ‌‌MyInt b = 2; ‌‌bool test = a < b; ‌‌bool test2 = a > b; ‌‌bool test3 = a <= b; ‌‌// [여기서 이상한 점] ‌‌// <=> 연산자를 사용했지만 ‌‌// 만약 value가 한 개가 아닌 여러개가 있다고 가정하면, ‌‌// 오퍼레이터 연산자가 어떤 변수를 기준으로 했는지 만들어졌는지 모호하다. ‌‌// 또 bool 타입으로 리턴을 안하고, string_ordering 이라는 타입이 무엇을 하는지 알 수가 없다. ‌‌// ordering 이라는 것이 크게 3가지로 구분할 수 있다. ‌‌// 1. strong ordering ‌‌// 2. weak ordering ‌‌// 3. partial ordering ‌‌// 위의 ordering들의 차이를 알기위해선 비교 특성에 대해 먼저 알고 있어야 한다. ‌‌// 비교 (Relational, Equivalence, Comparable) ‌‌// - 6종 비교 연산 지원 ==, !=, <, <=, >, >= (Relational 조건을 만족) ‌‌// - 모든 Equivalent한 값들은 서로 구분되지 않고 완전 똑같다 (Equivalence 조건을 만족) ‌‌// ex) 대소문자 구별 안하는 문자열 비교 abc Abc ‌‌// - a < b, a == b, a > b 중 하나는 참이다 (Comparable 조건을 만족) ‌‌// ex) float 비교할 때, b가 NaN(not a number)면 3연산이 다 true가 아님. ‌‌// Strong Ordering : Relational(O), Equivalence(O), Comparable(O) ‌‌// Weak Ordering : Relational(O), Comparable(O) ‌‌// Partial Ordering : Relational(O) ‌‌// weak ordering 같은 경우는 C++ 표준에서 사용하는 타입중에서 weak ordering으로 된 경우는 잘 없기 떄문에 직관적이지 않고, ‌‌// 보통 string ordering과 partial ordering이 친숙하고 직관적이다. ‌‌// 다시 위에서 이상한 점을 야기한대로 ‌‌// 변수가 여러개 있다고 가정하면, 선언된 순서대로 하나씩 테스트해보게 된다. ‌} ‌{ ‌‌int a1 = 100; ‌‌int b1 = 200; ‌‌auto ret = (a1 <=> b1); // Spaceship Operator 연산자를 사용해 타입이 strong_ordering인 ret 구조체를 할당. ‌‌// strong_ordering이라는 구조체를 내뱉어줬지만, 부호를 체크해서 추가적으로 어떤 결과물을 의미하는지 알 수가 있다. ‌‌if (ret < 0) ‌‌‌cout << "a < b" << endl; ‌‌else if (ret == 0) ‌‌‌cout << "a == b" << endl; ‌‌else if (ret > 0) ‌‌‌cout << "a > b" << endl; ‌} }

 

 

 

댓글