C ++에서 <=> 연산자는 무엇입니까?


215

C ++ 연산자 에 대해 배우려고하는 동안 cppreference.com 에서 이상한 비교 연산자를 발견했습니다 . * 는 다음과 같습니다.

여기에 이미지 설명을 입력하십시오

"글쎄, 이것이 C ++에서 일반적인 연산자라면, 그것들을 더 잘 배우는 것"이라고 생각했습니다. 그러나이 수수께끼를 설명하려는 모든 시도는 실패했습니다. 여기에서도 스택 오버플로에서 검색에 운이 없었습니다.

<=>C ++ 사이에 연결이 있습니까?

그리고이 연산자가 있다면 정확히 무엇을합니까?

* 한편 cppreference.com은 해당 페이지를 업데이트했으며 이제 <=>운영자 에 대한 정보가 포함되어 있습니다 .


82
@haccks : 아, 제발, 우리는 표준에 투표하지 않은 것들에 대해 많은 질문을했습니다. 우리는 C ++ 20 태그를 가지고 있습니다. 이런 종류의 물건은 주제에 매우 중요합니다.
Nicol Bolas

1
@ cubuspl42 bar< foo::operator<=><--연산자 와 같은 방법의 예입니다 .
Yakk-아담 Nevraumont

8
@haccks : 그렇습니다. C ++ 11과 마찬가지로 C ++ 11을 구현하는 컴파일러에 대한 태그입니다. 그리고 C ++ 14는 C ++ 14를 구현하는 컴파일러에 대한 태그입니다. 그리고 C ++ 17은 C ++ 17을 구현하는 컴파일러에 관한 것입니다. 아니요, C ++ 20은 C ++ 20에 대한 태그입니다. 그리고이 질문은 C ++ 20에 관한 것이므로 거기에 있습니다. 태그 자체가 아니라 태그 위키가 잘못되었습니다.
Nicol Bolas 1

답변:


180

이것을 3 방향 비교 연산자 라고합니다 .

P0515 논문 제안 에 따르면 :

새로운 3 방향 비교 연산자가 <=>있습니다. 발현은 a <=> b비교 객체를 반환 <0하는 경우 a < b, 비교 >0하는 경우를 a > b, 비교하고 ==0있는 경우 ab동일한 / 당량이다.

유형에 대한 모든 비교를 작성하려면 operator<=>적절한 카테고리 유형을 리턴하는 작성하십시오 .

  • 돌아 _ordering를 당신의 유형은 자연적으로 지원하는 경우 <, 우리는 효율적으로 생성 할 수 있습니다 <, >, <=, >=, ==, 그리고 !=; 그렇지 않으면 _equality를 반환 하면 효율적으로 ==! =를 생성 합니다.

  • 유형에 대해 a == b암시하는 경우 강한 반환 f(a) == f(b)(substitutability, 여기서 f는 비 개인적 const 인터페이스를 사용하여 액세스 할 수있는 비교 중심 상태 만 읽음), 그렇지 않으면 약한 값을 반환합니다.

cppreference는 말합니다 :

3 자 비교 연산자 식의 형식은 다음과 같습니다.

lhs <=> rhs   (1)  

이 표현식은 다음과 같은 객체를 반환합니다.

  • <0경우 비교lhs < rhs
  • >0경우 비교lhs > rhs
  • 비교하고 ==0있는 경우 lhsrhs동일한 / 당량이다.

93
"compares <0", "compares >0"및 "compares ==0"가 무엇을 의미 하는지에 대해 혼란스러워하는 사람들은 (논문처럼) <=>인수에 따라 음수, 양수 또는 0 값을 반환합니다. 많이 좋아 strncmp하고 memcmp.
Cornstalks

1
@Dai도 모두 불구 'a' < 'a'하고 'c' < 'a'모두 거짓, 'a' < 'a'그리고 'a' < 'c'수 없습니다. 강한 주문 다음 사실이다 : a != ba < b || b < a
Revolver_Ocelot

1
@Revolver_Ocelot Ah로 정의 operator==(T x, T y) { return !(x < y) && !(y < x); }하고 생성 할 수 있습니다 operator!=(T x, T y) { return (x < y) || (y < x); }-아-하! 물론 이것은 ==비교를 두 번 호출하지만 여전히 깔끔하기 때문에 사실보다 덜 효율적 입니다.
다이

3
"강한 수익률"과 "약한 수익률"이란 무엇입니까?
lucidbrot

2
@hkBattousai는 비교 될 때 객체가 반환되는 것을 의미 < 0합니다. 경우 즉, a < b다음, (a <=> b) < 0항상 사실이다.
rmobis

116

2017년 11월 11일 상기 ISO C ++위원회 채용 허브 서터 용의 제안 <=> "우주선"삼원 비교 연산자 에 추가 된 새로운 기능들 중 하나로서 20 ++ C . 일관성있는 비교 Sutter 라는 논문 에서 Maurer와 Brown은 새로운 디자인의 개념을 보여줍니다. 제안에 대한 개요는 다음 기사에서 발췌 한 내용입니다.

a <=> b 표현식 a <b 인 경우 <0 을 비교 하고 a> b 인 경우 > 0을 비교 하고 a와 b가 같거나 동등한 경우 == 0 을 비교하는 객체를 반환합니다 .

일반적인 경우 : 유형 XY 유형의 모든 비교를 작성 하고 멤버 별 의미를 쓰려면 다음과 같이 작성하십시오.

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

고급 사례 : 당신의 유형에 대한 모든 비교 쓰려면 X 유형 Y 단지 쓰기, 운영자 <=> 소요 Y를 사용할 수 있습니다 = 기본을 원하는 경우 memberwise 의미를 얻기 위해, 반환 적절한 범주 유형 :

  • 유형이 자연스럽게 <을 지원 하면 _ordering을 반환하면 대칭 < , > , <= , > = , ==! =을 . 그렇지 않으면 _equality를 반환하고 대칭 ==! =을 효율적으로 생성 합니다.
  • 타입 a == b 인 경우 strong_을 반환 합니다. 의미 F (A) == F (B) (대체 가능성, f는 공중 사용하여 액세스 할 경우에만 비교 - 돌출 상태를 읽어 CONST의 회원), 그렇지 않으면 반환 weak_ .

비교 카테고리

5 개의 비교 범주는 std::유형 으로 정의되며 각각은 다음과 같은 사전 정의 된 값을 갖습니다.

+--------------------------------------------------------------------+
|                  |          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 |             |
+------------------+------+------------+---------------+-------------+

이러한 유형 간의 암시 적 변환은 다음과 같이 정의됩니다.

  • strong_ordering값 { less, equal, greater}는 암시 적으로 변환 :
    • weak_ordering값 { less, equivalent, greater}
    • partial_ordering값 { less, equivalent, greater}
    • strong_equality 값이 {unequal, equal, unequal}
    • weak_equality값이 { nonequivalent이고equivalent, nonequivalent}
  • weak_ordering 값이 {less, equivalent, greater}는 암시 적으로 변환 :
    • partial_ordering 값이 {less, equivalent, greater}
    • weak_equality값이 { nonequivalent이고equivalent, nonequivalent}
  • partial_ordering 값이 {less , equivalent, greater, unordered}는 암시 적으로 변환 :
    • weak_equality값으로 { nonequivalent, equivalent,nonequivalent , nonequivalent}
  • strong_equality값이 { equal, unequal} 인 경우 암시 적으로 다음으로 변환됩니다.
    • weak_equality값이 { equivalent이고nonequivalent } 인

3 방향 비교

<=>토큰이 도입된다. 문자 순서 <=><= > 는 이전 소스 코드에서로 . 예를 들어, X<&Y::operator<=>의미를 유지하려면 공백을 추가해야합니다.

과부하 연산자 <=>는 3 방향 비교 기능이며보다 높고 <낮습니다 <<. 리터럴과 비교할 수있는 유형을 0리턴하지만 표현식 템플리트를 지원하는 등 다른 리턴 유형이 허용됩니다. 모두<=>언어와 표준 라이브러리에 정의 된 연산자는 위에서 언급 한 5 std::가지 비교 범주 유형 중 하나를 반환 합니다.

언어 유형의 경우 다음과 같은 기본 <=>제공 동일한 유형 비교가 제공됩니다. 달리 언급 된 경우를 제외하고 모두 constexpr 입니다. 스칼라 승격 / 변환을 사용하여 이러한 비교를 이기종으로 호출 할 수 없습니다.

  • 를 들어 bool, 통합 및 포인터 타입, <=>반환 strong_ordering.
  • 포인터 유형의 경우, 다른 cv-qualifications와 파생 된 대 기본 변환은 동질적인 내장을 호출 할 수 있습니다.<=> 있으며 내장 이기종이 operator<=>(T*, nullptr_t)있습니다. 동일한 객체 / 할당에 대한 포인터 비교는 상수 표현식입니다.
  • 기본 부동 소수점 유형의 경우 <=>반환partial_ordering 하고 더 큰 부동 소수점 유형으로 인수를 확장하여 이기종으로 호출 할 수 있습니다.
  • 열거 형의 경우, <=>열거 형의 기본 유형과 동일을 반환합니다.<=> .
  • 의 경우 nullptr_t, <=>반환 strong_ordering항상 수율equal .
  • 복사 가능한 배열의 경우 T[N] <=> T[N]와 동일한 유형 반환 T<=>및 수행 사전 편찬 elementwise 비교. 없습니다<=>다른 배열 .
  • 내용은 void더 없다 <=>.

이 작업자의 내부 작동을보다 잘 이해하려면 원본 용지 를 읽으십시오 . 이것은 내가 검색 엔진을 사용하여 찾은 것입니다.


1
마치 cpp가 충분히 복잡하지 않은 것처럼. 단순히 비교 방법을 쓰지 않겠습니까?
Leandro

6
@Leandro 우주선 연산자 그 비교 방법입니다. 또한 Just Just Works와 6 개의 다른 비교 연산자를 쓰거나 삭제합니다. 6 개의 개별 상용구에 대해 작성된 하나의 비교 연산자 함수를 사용하겠습니다.
anonymous

주의 _equality가 밝혀졌다 : 유형이 죽은 <=>재생 잘와 네 개의 관계 연산자가 아니라뿐만 아니라 함께 두 평등 사업자 (비록 당신이 그들 모두를 원하는 일반적인 경우를 지원하기 위해 어떤 강렬한 문법적있다).
Davis Herring

12

이 답변은 참조 웹 페이지가 변경된 이후 관련이 없습니다.

참조하고 있는 웹 페이지 가 손상되었습니다. 그날 많은 부분을 편집하고 있었고 다른 부분은 동기화되지 않았습니다. 내가 보았을 때의 상태는 다음과 같습니다.

페이지 상단에는 현재 존재하는 비교 연산자 (C ++ 14)가 표시됩니다. 없습니다 <=>.

페이지 하단에 동일한 연산자를 나열해야하지만이 제안을 추가하고 추가했습니다.

gcc<=>아직 알지 못하고 (와 함께 -std=c++14, 결코하지 않을 것이므로)a <= > b 입니다. 오류 메시지에 대한 설명입니다.

5 년 후에 같은 것을 시도하면 아마도 더 나은 오류 메시지를 보게 될 것입니다. <=> not part of C++14.


1
연결하는 별도의 페이지와 마찬가지로 웹 페이지 OP가 연결됩니다. <=>C ++ 20 이후 (C ++ 20 이후) 레이블을 사용 하여 운영자에게 적합한 표준 버전을 알려줍니다. 표준 레이블링은 cppreference.com이 따르는 규칙입니다. 물론 당신을 위해 그것을 지원하기 위해 타임 머신으로 돌아온 컴파일러는 없지만 cpprefernce는 (올바로) 기대할 것을 알려줍니다.
스펜서

예,하지만 ... 대답이 없습니다. 댓글을 달거나 ...
qlp

2
질문과 동일한 웹 페이지에 연결하려고했지만 놓쳤습니다. 다른 답변이하지 않은 질문 부분에 답한 것 같습니다. 다른 사람들이 이미 대답했기 때문에 나는 대담한 질문을 무시했습니다.
Stig Hemmer
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.