왜“b <a? “a <b? b : a”max 템플릿을 구현 하시겠습니까?


154

C ++ 템플릿-전체 안내서, 2 판 에서는 최대 템플릿을 소개합니다 .

template<typename T>
T max (T a, T b)
{
  // if b < a then yield a else yield b
  return  b < a ? a : b;
}

그리고 “b < a ? a : b”대신 다음을 사용하여 설명합니다 “a < b ? b : a”.

[StepanovNotes]에 따른 max () 템플릿은 의도적으로“b <a? “a <b? b : a”를 사용하여 두 값이 같지만 같지 않더라도 함수가 올바르게 작동하는지 확인하십시오.

" even if the two values are equivalent but not equal." 를 이해하는 방법 ? “a < b ? b : a”나에게 동일한 결과가있는 것 같습니다.


8
나에게 잘못 외모는 ... 두 답변은 "올바른"하지만 경우에 ab있는 해당 , 다음 !(a < b) && !(b < a)사실, 그렇게 a < b하고 b < a모두 거짓이다, 그래서에 b < a ? a : b, b당신은 당신이 원하는 ... 원하는하지 않은 반환됩니다 a < b ? b : a.
Holt

1
당신은 종종 상당 구별 할 수 ab함께 std::addressof등. 알.
Caleth

14
a = max(a, b);반복적으로 수행 하면 a불필요하게 교체 하지 않을 수 있습니다 .
Bo Persson 2016 년

2
BTW이 템플릿 그렇지 않으면, 당신은 쓸모없는 사본의 무리를하고있는 (그리고 무시하려고하는, const를-참조에 의한 매개 변수를 사용하고 const를 참조하여 그들을 반환해야 a사본 a).
Holt

3
@Caleth : 동등성과 동등성을 갖는 표준 유형은 CaseInsensitiveString입니다. 해당 유형의 경우 a <A 또는 A <a. 그러나 std::addressof관련이 없습니다. 사실, T max(T a, T b)우리는 이미 알고 addressof(a) != addressof(b)있습니다.
MSalters 2016 년

답변:


150

std::max(a, b)실제로 a는 둘이 동일 할 때 리턴하도록 지정됩니다 .

즉의 실수로 간주 Stepanov 가 제공하는 유용한 속성을 나누기 때문에 다른 사람 ab당신은 항상 종류를 함께 할 수 있습니다 {min(a, b), max(a, b)}; 이를 위해 인수가 동등한 경우 max(a, b)반환 하려고 합니다 b.


48
그 링크에서 "저는 그렇게하는 사람들을 비난하기가 어렵습니다. 결국 그들은 저에 의해 작성된 max 의 C ++ 표준 사양을 따르고 있습니다. 제가 잘못 알고있는 데는 몇 년이 걸렸습니다." - 와!
Jack Aidley

23
당신은 할 수 없습니다 {min(a, b), max(b, a)}?
Captain Man

12
@CaptainMan : 예,하지만 여전히 덜 명확합니다. 나는 max(a,b)if-and-only-if min(a,b)리턴 b 를 리턴하는 논리적 인 의미를 가지고 있으며, 그 반대의 경우도 마찬가지 이며 (정렬되지 않은) 세트 {min(a,b), max(a,b)}는 항상 같습니다 {a,b}.
잭 에이 들리

5
@ jpmc26 : 예를 들어 시간별로 이벤트 목록을 정렬하는 경우 입력에서 정확히 한 번 표시되는 각 이벤트를 출력에 정확하게 한 번 표시하도록 정렬 작업이 안정적인지 여부를 신경 쓸 필요가 없습니다. 복제 된 이벤트를 찾아서 제거하는 것과 같은 특정 작업은 완전한 순서를 사용해야 할 수도 있지만, 다른 경우에는 동시 이벤트를 임의의 순서로 나열하는 것이 허용되지만 복제 또는 생략하지 않을 수도 있습니다.
supercat

2
적용 @supercat minmax아무것도하지만, 타임 스탬프 이 시나리오에서 (정렬 키) 이해되지 않는다. 평등이 상호 교환 성을 의미하지 않는 경우 이벤트 (객체) 자체도 비교할 수 없습니다. 정렬 메커니즘으로 의미 {min(a, b), max(a, b)}있는 유일한 방법 은 개체가 상호 교환 가능한 경우입니다.
jpmc26 2016 년

62

이 답변은 주어진 코드가 C ++ 표준 관점에서 잘못된 이유를 설명하지만 상황에 맞지 않습니다.

상황에 대한 설명은 @TC 의 답변 을 참조하십시오 .


표준은 std::max(a, b)다음과 같이 정의 합니다 [alg.min.max] (강조는 내 것입니다) :

template<class T> constexpr const T& max(const T& a, const T& b);

요구 사항 : 유형 T가 LessThanComparable (표 18)입니다.

결과 : 더 큰 값.

비고 : 인수가 동일한 경우 첫 번째 인수를 반환합니다.

여기서 동등한 !(a < b) && !(b < a)것은 true [alg.sorting # 7] 입니다.

특히 경우 ab동등한 양 a < b하고 b < a있는 false우측의 값이되도록 :하므로, 조건 연산자에 반환한다 a그래서, 오른쪽에 있어야한다 :

a < b ? b : a

... 정답 인 것 같습니다. 이것은 libstdc ++libc ++에서 사용하는 버전 입니다.

따라서 인용문의 정보는 현재 표준에 따라 잘못된 것처럼 보이지만 정의 된 컨텍스트가 다를 수 있습니다.


4
문제를 설명하는 Godbolt 링크 (의 정의에 @songyuanyao 감사 X).
Holt

1
@JackAidley 나는 추론이 현재 표준을 목표로하도록 지정하기 위해 답을 편집했습니다.
Holt

@ codekaizer 나는 실제로 "우리가 equiv (a, b)를! comp (a, b) &&! comp (b, a)로 정의하면"이라고 언급했습니다 . 링크를 더 나은 인용문으로 변경했습니다 (표준에서 아래 3 줄 ...).
Holt

1
깜짝 아무도 부동 소수점 언급하지 않았다 a<b그리고 b<a그들이있는 거 정렬되지 않은 (하나 또는 둘 모두 NaN이, 그래서 때문에 모두 거짓이 될 수 ==도 거짓이다). 그것은 일종의 등가로 보일 수 있습니다. 느슨하게 관련됨 : x86의 maxsd a, b명령어 구현 a = max(b,a) = b < a ? a : b. ( x86에서 분기없는 FP 최소 및 최대를 제공하는 명령어는 무엇입니까? ). 이 명령어는 소스 피연산자 (두 번째 것)를 정렬되지 않은 상태로 유지하므로 NaN이 있으면 배열을 반복하여 NaN을 제공합니다. 그러나 max_seen = max(max_seen, a[i])NaN은 무시합니다.
Peter Cordes 2016 년


21

요점은 동등 할 때 어떤 것이 반환되어야 하는가이다. 이 경우에는 첫 번째 인수 std::max를 반환 a해야합니다.

같으면를 반환합니다 a.

따라서 a < b ? b : a사용해야합니다. 반면에 잘못 b < a ? a : b;반환 b됩니다.

(@Holt가 말했듯이 인용문은 정반대로 보입니다.)

"두 값은 같지만 같지 않다"는 의미는 비교할 때 동일한 값을 갖지만 다른 측면에서는 다른 객체 일 수 있습니다.

예 :

struct X { int a; int b; };
bool operator< (X lhs, X rhs) { return lhs.a < rhs.a; }
X x1 {0, 1};
X x2 {0, 2};
auto x3 = std::max(x1, x2); // it's guaranteed that an X which cantains {0, 1} is returned

1
와 동등한 경우 왜 std::max(a, b)반환 해야하는지 자세히 설명해 주 시겠습니까? aab
眠 り ネ ロ ク

4
@ ネ ロ ク- 표준 부분에서 임의의 선택입니다 . 좋은 것이면 논쟁의 여지가 있지만.
StoryTeller-Unslander Monica 2006 년

그것은 단지 나인가 아니면 질문과 모순 되는가? 경우 ab동일합니다, 다음 !(a < b) && !(b < a)사실, 그렇게 a < b하고 b < a... 그래서 거짓?
Holt

2
@ ネ ロ ク 나는 표준이 결정하기를 원한다고 가정한다. 그들이 반환되어야하는 것과 동등한 경우.
songyuanyao

1
왜 객체가 "동등"하지만 "동일"하지 않는지에 대한 기억을 새로 고쳐 주셔서 감사합니다.
Jeff Walker
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.