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있는 경우 a와 b동일한 / 당량이다.

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

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

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

cppreference는 말합니다 :

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

lhs <=> rhs   (1)  

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

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

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

1
@Dai도 모두 불구 'a' < 'a'하고 'c' < 'a'모두 거짓, 'a' < 'a'그리고 'a' < 'c'수 없습니다. 강한 주문 다음 사실이다 : a != b→a < 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 을 비교하는 객체를 반환합니다 .

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

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.