다음 구조체의 두 인스턴스를 비교하면 오류가 발생합니다.
struct MyStruct1 {
MyStruct1(const MyStruct2 &_my_struct_2, const int _an_int = -1) :
my_struct_2(_my_struct_2),
an_int(_an_int)
{}
std::string toString() const;
MyStruct2 my_struct_2;
int an_int;
};
오류는 다음과 같습니다.
오류 C2678 : 바이너리 ‘==’: ‘myproj :: MyStruct1’유형의 왼쪽 피연산자를 사용하는 연산자를 찾을 수 없습니다 (또는 허용되는 변환이 없음).
왜?
답변
C ++에서 struct
s에는 기본적으로 생성 된 비교 연산자가 없습니다. 직접 작성해야합니다.
bool operator==(const MyStruct1& lhs, const MyStruct1& rhs)
{
return /* your comparison code goes here */
}
답변
C ++ 20은 기본 비교, 일명 “우주선”을 도입했습니다operator<=>
.이를 통해 컴파일러 생성 <
/ <=
/ ==
/ !=
/ >=
/ 및 / 또는 >
명백한 / 순진한 (?) 구현으로 연산자 를 요청할 수 있습니다 .
auto operator<=>(const MyClass&) const = default;
…하지만 더 복잡한 상황에 맞게 사용자 정의 할 수 있습니다 (아래에서 설명). 타당성과 논의가 포함 된 언어 제안 은 여기 를 참조 하십시오 . 이 답변은 C ++ 17 및 이전 버전과 관련이 있으며 구현을 사용자 정의해야하는시기에 대한 통찰력을 제공합니다.operator<=>
… .
이전에 표준화하지 않은 것은 C ++에 약간 도움이되지 않을 수 있지만, 종종 구조체 / 클래스에는 비교 에서 제외 할 데이터 멤버 (예 : 카운터, 캐시 된 결과, 컨테이너 용량, 마지막 작업 성공 / 오류 코드, 커서)가 있습니다. 다음을 포함하되 이에 국한되지 않는 무수한 사항에 대한 결정을 내릴 수 있습니다.
- 먼저 비교할 필드, 예를 들어 특정
int
구성원을 비교하면 동일하지 않은 개체의 99 %를 매우 빠르게 제거 할 수있는 반면map<string,string>
멤버는 종종 동일한 항목을 가지고 있고 비교하는 데 상대적으로 비용이 많이들 수 있습니다. 값이 런타임에로드되면 프로그래머는 다음과 같은 통찰력을 가질 수 있습니다. 컴파일러는 가능하지 않다 - 문자열 비교 : 대소 문자 구분, 공백 및 구분 기호의 동등성, 이스케이프 규칙 …
- float / double을 비교할 때 정밀도
- NaN 부동 소수점 값이 동일한 것으로 간주되어야하는지 여부
- 포인터 또는 지적 된 데이터 비교 (후자의 경우 포인터가 배열에 대한 것인지 비교가 필요한 객체 / 바이트 수를 아는 방법)
- 정렬되지 않은 컨테이너를 비교할 때 순서가 중요한지 (예 :
vector
,list
), 그렇다면 비교하기 전에 제자리에서 정렬하는 것이 좋은지 비교가 완료 될 때마다 임시를 정렬하기 위해 추가 메모리를 사용하는 것이 좋은지 여부 - 현재 비교해야 할 유효한 값을 보유하고있는 배열 요소의 수 (어딘가에 크기 또는 센티넬이 있습니까?)
union
비교할의 멤버- 정규화 : 예를 들어 날짜 유형은 범위를 벗어난 날짜 또는 월을 허용 할 수 있습니다. 또는 합리적 / 분수 객체는 6/8을 가질 수 있고 다른 하나는 3 / 4ers를 가질 수 있으며 이는 성능상의 이유로 수정합니다. 별도의 정규화 단계로 느리게; 비교하기 전에 정규화를 트리거할지 여부를 결정해야 할 수 있습니다.
- 약한 포인터가 유효하지 않을 때해야 할 일
- 구현하지 않는 회원들과 기지 처리하는 방법을
operator==
스스로 (하지만있을 수 있습니다compare()
또는operator<
또는str()
또는 게터를 …) - 다른 스레드가 업데이트하려는 데이터를 읽고 / 비교하는 동안 수행해야하는 잠금
따라서 특정 구조에 대해 비교가 의미하는 바에 대해 명시 적으로 생각할 때까지 오류가 발생하는 것이 좋습니다. 컴파일하는 대신 런타임에 의미있는 결과를 제공하지 않습니다 .
즉, bool operator==() const = default;
“순진한”멤버 별 ==
테스트 가 괜찮다고 결정할 때 C ++에서 말할 수 있다면 좋을 것 입니다. 동일에 대한 !=
. 을 감안할 때 여러 회원 / 기지, “기본” <
, <=
, >
, 및 >=
구현은 희망하지만 보인다 – 선언의 수 있지만, 원에 의해 그룹화, 염기는 회원 전에 반드시 인 (회원 주문에 대한 명령형 충돌 주어진 무슨 일이 매우 가능성의 순서에 근거하여 계단식 의존적 사용 전 접근성, 건설 / 파괴). 보다 광범위하게 유용하게 사용하려면 C ++는 선택을 안내하는 새로운 데이터 멤버 /베이스 주석 시스템이 필요합니다.하지만 AST 기반 사용자 정의 코드 생성과 이상적으로 결합 된 표준에 포함되어 있으면 좋을 것입니다. 그것’
평등 연산자의 일반적인 구현
그럴듯한 구현
그것은의 가능성이 합리적이고 효율적으로 구현 될 것이라고 :
inline bool operator==(const MyStruct1& lhs, const MyStruct1& rhs)
{
return lhs.my_struct2 == rhs.my_struct2 &&
lhs.an_int == rhs.an_int;
}
이것이 필요합니다 operator==
위해 MyStruct2
너무.
이 구현의 의미와 대안은 아래 MyStruct1의 세부 사항에 대한 토론 제목 아래에 설명되어 있습니다.
==, <,> <= 등에 대한 일관된 접근 방식
std::tuple
의 비교 연산자 를 활용 하여 자신의 클래스 인스턴스를 비교하는 것은 쉽습니다 std::tie
. 원하는 비교 순서로 필드에 대한 참조 튜플을 만드는 데 사용 하면됩니다. 여기 에서 내 예를 일반화 :
inline bool operator==(const MyStruct1& lhs, const MyStruct1& rhs)
{
return std::tie(lhs.my_struct2, lhs.an_int) ==
std::tie(rhs.my_struct2, rhs.an_int);
}
inline bool operator<(const MyStruct1& lhs, const MyStruct1& rhs)
{
return std::tie(lhs.my_struct2, lhs.an_int) <
std::tie(rhs.my_struct2, rhs.an_int);
}
// ...etc...
비교할 클래스를 “소유”(즉, 기업 및 타사 라이브러리가있는 요소를 편집 할 수 있음) 할 때 특히 C ++ 14가 return
명령문 에서 함수 반환 유형을 추론 할 준비가되어 있으면 “를 추가하는 것이 더 좋습니다. “멤버 함수를 비교할 수있는 클래스에 연결합니다.
auto tie() const { return std::tie(my_struct1, an_int); }
그런 다음 위의 비교는 다음과 같이 단순화됩니다.
inline bool operator==(const MyStruct1& lhs, const MyStruct1& rhs)
{
return lhs.tie() == rhs.tie();
}
보다 완전한 비교 연산자 세트를 원한다면 부스트 연산자 (검색)를 제안 less_than_comparable
합니다. 어떤 이유로 부적합한 경우 지원 매크로 (온라인) 아이디어가 마음에들 수도 있고 그렇지 않을 수도 있습니다 .
#define TIED_OP(STRUCT, OP, GET_FIELDS) \
inline bool operator OP(const STRUCT& lhs, const STRUCT& rhs) \
{ \
return std::tie(GET_FIELDS(lhs)) OP std::tie(GET_FIELDS(rhs)); \
}
#define TIED_COMPARISONS(STRUCT, GET_FIELDS) \
TIED_OP(STRUCT, ==, GET_FIELDS) \
TIED_OP(STRUCT, !=, GET_FIELDS) \
TIED_OP(STRUCT, <, GET_FIELDS) \
TIED_OP(STRUCT, <=, GET_FIELDS) \
TIED_OP(STRUCT, >=, GET_FIELDS) \
TIED_OP(STRUCT, >, GET_FIELDS)
… 그런 다음 사용할 수 있습니다 …
#define MY_STRUCT_FIELDS(X) X.my_struct2, X.an_int
TIED_COMPARISONS(MyStruct1, MY_STRUCT_FIELDS)
(C ++ 14 멤버 타이 버전은 여기 )
MyStruct1의 세부 사항에 대한 토론
독립형 대 멤버를 제공하는 선택에 영향을 미칩니다 operator==()
…
독립 구현
당신은 흥미로운 결정을 내릴 수 있습니다. 클래스를에서 암시 적으로 구성 할 수 있으므로 MyStruct2
독립 / 비 멤버 bool operator==(const MyStruct2& lhs, const MyStruct2& rhs)
함수가 지원합니다 …
my_MyStruct2 == my_MyStruct1
… 먼저에서 임시 파일 MyStruct1
을 my_myStruct2
만든 다음 비교를 수행합니다. 이것은 MyStruct1::an_int
생성자의 기본 매개 변수 값인 -1
. an_int
의 구현에 비교 를 포함하는지 여부에 따라 operator==
a MyStruct1
는 의 멤버와 MyStruct2
동일하게 비교 되는 a와 같을 수도 있고 그렇지 않을 수도 있습니다 ! 또한 임시 생성 은 기존 멤버를 임시로 복사 하고 비교 후에 버려야하기 때문에 매우 비효율적 인 작업 일 수 있습니다 . (물론, 당신은 그 생성자를 만들 거나의 기본값을 제거함으로써 비교를위한 s의 암시 적 생성을 막을 수 있습니다.)MyStruct1
my_struct_2
MyStruct1
my_struct2
MyStruct1
explicit
an_int
회원 구현
당신이 암시 건설 피하려면 MyStruct1
A로부터를 MyStruct2
, 비교 연산자 A는 멤버 함수를합니다
struct MyStruct1
{
...
bool operator==(const MyStruct1& rhs) const
{
return tie() == rhs.tie(); // or another approach as above
}
};
메모 const
만을 멤버 구현에 필요한 – – 키워드를 객체를 비교하는을 수정하지 않는 컴파일러 조언 때문에 허용 될 수 const
객체.
가시적 표현 비교
원하는 유형의 비교를 얻는 가장 쉬운 방법은 다음과 같습니다.
return lhs.to_string() == rhs.to_string();
… 그것은 종종 매우 비싸다-그것들 string
은 단지 버려지기 위해 고통스럽게 만들어졌습니다! 부동 소수점 값이있는 유형의 경우 표시되는 표현을 비교하면 표시된 자릿수가 비교 중에 거의 동일한 값이 동일하게 처리되는 허용 오차를 결정합니다.
답변
에 operator ==
대해 명시 적으로 정의해야합니다 MyStruct1
.
struct MyStruct1 {
bool operator == (const MyStruct1 &rhs) const
{ /* your logic for comparision between "*this" and "rhs" */ }
};
이제 == 비교는 이러한 객체 2 개에 대해 합법적입니다.
답변
C ++ 20에서 시작, 기본 비교 연산자 (의 전체 세트를 추가 할 수 있어야한다 ==
, <=
선언하여 클래스 등) 기본 세 방향 비교 연산자를 다음과 같이 ( “우주선”연산자) :
struct Point {
int x;
int y;
auto operator<=>(const Point&) const = default;
};
호환 C ++ 20 컴파일러를 사용하면 MyStruct2의 정의가 호환된다는 가정하에 MyStruct1 및 MyStruct2에 해당 행을 추가하는 것만으로 동등성 비교를 허용 할 수 있습니다.
답변
C 또는 C ++의 구조체에서는 비교가 작동하지 않습니다. 대신 필드로 비교하십시오.
답변
기본적으로 구조체에는 ==
연산자 가 없습니다 . 자체 구현을 작성해야합니다.
bool MyStruct1::operator==(const MyStruct1 &other) const {
... // Compare the values, and return a bool result.
}
답변
기본적으로 == 연산자는 기본 요소에 대해서만 작동합니다. 코드가 작동하도록하려면 구조체에 대한 == 연산자를 오버로드해야합니다.