C ++ 20에서 사용자 정의 우주선 연산자 구현에 대해 동등 연산자가 정의되지 않음


51

<=>C ++ 20 의 새로운 우주선 연산자 로 이상한 행동을하고 있습니다. 와 함께 Visual Studio 2019 컴파일러를 사용하고 /std:c++latest있습니다.

이 코드는 예상대로 정상적으로 컴파일됩니다.

#include <compare>

struct X
{
    int Dummy = 0;
    auto operator<=>(const X&) const = default; // Default implementation
};

int main()
{
    X a, b;

    a == b; // OK!

    return 0;
}

그러나 X 를 이것으로 변경 하면 :

struct X
{
    int Dummy = 0;
    auto operator<=>(const X& other) const
    {
        return Dummy <=> other.Dummy;
    }
};

다음과 같은 컴파일러 오류가 발생합니다.

error C2676: binary '==': 'X' does not define this operator or a conversion to a type acceptable to the predefined operator

나는 이것을 clang에서도 시도해 보았고 비슷한 행동을 얻었습니다.

기본 구현이 operator==올바르게 생성되는 이유에 대한 설명에 감사 하지만 사용자 지정 구현 은 그렇지 않습니다.

답변:


50

이것은 의도적으로 설계된 동작입니다.

[class.compare.default] (강조 광산)

3 클래스 정의가 == 연산자 함수를 명시 적으로 선언하지 않고 기본 3 방향 비교 연산자 함수를 선언하면 3 자 비교 연산자 함수 ==와 동일한 액세스 권한으로 연산자 함수가 내재적으로 선언됩니다. ==클래스 X에 대해 암시 적으로 선언 된 연산자는 인라인 멤버이며 X의 정의에서 기본값으로 정의됩니다.

기본값 <=>은 합성 된 ==것을 허용 합니다. 이론적 근거는 같은 클래스 std::vector는 기본값을 사용할 수 없다는 것 <=>입니다. 또한 <=>for를 사용 하는 ==것이 벡터를 비교하는 가장 효율적인 방법은 아닙니다. <=>정확한 순서를 제시해야하지만 ==크기를 먼저 비교하여 조기에 구제 할 수 있습니다.

클래스가 3 방향 비교에서 특별한 작업을 수행하는 경우 클래스에서 특별한 작업을 수행해야합니다 ==. 따라서 감지 할 수없는 기본값을 생성하는 대신, 언어는이를 프로그래머에게 맡깁니다.


4
우주선이 버그가 아닌 한 확실히 합리적입니다. 잠재적으로 비효율적이지만 ...
중복 제거기

1
@ 중복 제거기-감수성이 주관적입니다. 일부는 자동 생성 된 비효율적 인 구현이 합리적이지 않다고 말합니다.
StoryTeller-Unslander Monica

45

이 기능의 표준화 동안, 평등과 순서는 논리적으로 분리되어야한다고 결정되었다. 따라서 평등 테스트 ( ==!=)를 사용하면 결코 호출 되지 않습니다operator<=> . 그러나 단일 선언으로 두 가지를 모두 기본값으로 지정할 수있는 것이 여전히 유용한 것으로 나타났습니다. 따라서 default operator<=>인 경우 operator==나중에 정의하거나 이전에 정의하지 않은 경우 기본값으로 설정하기로 결정했습니다 .

에 관해서는 이 결정이 이루어진 이유는 , 기본적인 추론은 다음과 같이 간다. 고려하십시오 std::string. 두 줄의 순서는 사전 식입니다. 각 문자는 다른 문자열의 각 문자와 비교하여 정수 값을 갖습니다. 첫 번째 불평등은 주문 결과입니다.

그러나 스트링의 동등성 테스트에는 단락이 있습니다. 두 문자열의 길이가 동일하지 않으면 문자 비교를 전혀 할 필요가 없습니다. 그들은 같지 않습니다. 따라서 누군가가 평등 테스트를 수행하는 경우 단락 할 수 있다면 긴 형식을 원하지 않습니다.

사용자 정의 순서가 필요한 많은 유형은 평등 테스트를위한 일부 단락 메커니즘을 제공합니다. 사람들이 구현 operator<=>만하고 잠재적 인 성능을 버리지 못하도록 모든 사람이 효과적으로 두 가지를 모두 수행하도록합니다.


5
이것은 대답보다 훨씬 더 나은 설명입니다
메모

17

다른 답변은 언어가 왜 이런지 잘 설명합니다. 명확하지 않은 경우를 대비하여 사용자 operator<=>가 defaulted를 제공하는 것이 가능하다는 것을 추가하고 싶었습니다 operator==. 기본값을 명시 적으로 작성하면됩니다 operator==.

struct X
{
    int Dummy = 0;
    auto operator<=>(const X& other) const
    {
        return Dummy <=> other.Dummy;
    }
    bool operator==(const X& other) const = default;
};
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.