우리는 최소치와 최대치를 정확하게 계산했습니까?
12881 단어 oopalgorithmstutorialcpp
월터는 이러한 알고리즘의 몇 가지 문제를 제기했다. 서로 다른 유형의 문제부터 파라미터를 어떻게 효과적으로 전달하는지에 이르기까지. 그러나 나는 가능한 문제 하나만 주목하고 싶다.
min
와max
의C++20 스타일의 간단한 실현을 살펴보자.auto min(auto left, auto right) {
return left < right ? left : right;
}
auto max(auto left, auto right) {
return right < left ? left : right;
}
그게 무슨 문제야?만약
left == right
에 무슨 일이 일어났다면?왼쪽과 오른쪽이 같을 때
min
와 max
는 같은 값을 되돌려줍니다.즉right
.그런데 이게 맞는 건가요?
월트의 말에 의하면 이것은 옳지 않다고 한다.그는 자신의 의견을 제시했지만 2014년 위원회에서 이 의견들이 흥미롭지 않다고 느꼈다.
그들은 틀림없이 매우 재미있을 거야, 여기서 토론할 수 있어.나는 그가 우리가 생각하지 못할 요점을 제시했다고 생각한다.
어떤 사람들은 그의 생각을 반대한다. 왜냐하면 어느 것으로 돌아가는 것이 중요하지 않기 때문이다. 왜냐하면 if
left == right
의 값은 구분할 수 없기 때문이다.사실은 반드시 이와 같지 않다.
그는 학생반의 예를 들었다.
struct Student {
std::string name;
int id;
inline static int registrar = 0;
Student(const std::string& iName):
name(iName), id(registrar++) {}
friend bool operator<(const Student& lhs,
const Student& rhs) {
return lhs.name < rhs.name;
}
};
이런 상황에서 우리는 두 학생이 같은 이름을 가지고 있다면, 이것은 불가능한 것이 아니라, 그들을 대표하는 대상이 구분할 수 없는 것이 아니라는 것을 관찰할 수 있다.그것들은 확실히 다르다id
s.그러나 월터 공유의 실현에 따라
min
와 max
는 모두 되돌아온다right
.만약 우리가 이러고 싶지 않다면, 우리는 서로 다른 방식으로 비교 연산자를 실현해야 한다고 말할 수 있다.사실 우리는
Student::id
를 비교 연산자의 일부분으로 만들어야 이 문제가 없을 것이다.나는 만약 우리가 이러한 논리 연산자를 필요로 하고, 두 대상이 구분할 수 없는 것이 아니라 서로 같게 계산될 수 있다고 걱정한다면, 우리는 논리 연산자를 수정해야 한다고 느낀다.
C++20부터, 우리는spaceship 조작부호를 사용하여 모든 비교 조작부호를 자동으로 정의할 수 있습니다.
Student
클래스에서는 다음과 같이 표시됩니다.auto operator<=>(const Student&) const = default;
컴파일러가 조작부호를 생성할 수 있다면, '왼쪽에서 오른쪽까지의 모든 기본 클래스와 클래스의 모든 비정상적인 구성원의 성명 순서' 를 고려할 것입니다.이것은 고려할 것을 의미한다
Student::id
. 따라서 구분할 수 없는 두 개의 대상이 있어야 하며, 각 필드에 두 개의 값이 같은 대상이 있어야 한다.그럼 어느 쪽이 반송되는지는 정말 중요하지 않아요.너는 논리적으로 말하자면, 우리는 모든 상황에서 이렇게 할 수 없다고 말할 수 있다.너는 옳을 수도 있고, 너는 이런 사례를 제기할 수도 있지만, 나는 이것이 주요 원인이라고 생각하지만, 월트의 불평은 고려되지 않았다.
아니면 그들인가?
어디 보자the MSVCC implementation.
이곳은 간략한 발췌문이다.
template <class _Ty>
_NODISCARD _Post_equal_to_(_Left < _Right ? _Right : _Left) constexpr const _Ty& //
(max) (const _Ty& _Left, const _Ty& _Right) noexcept(noexcept(_Left < _Right)) /* strengthened */ {
// return larger of _Left and _Right
return _Left < _Right ? _Right : _Left;
}
template <class _Ty>
_NODISCARD _Post_equal_to_(_Right < _Left ? _Right : _Left) constexpr const _Ty& //
(min) (const _Ty& _Left, const _Ty& _Right) noexcept(noexcept(_Right < _Left)) /* strengthened */ {
// return smaller of _Left and _Right
return _Right < _Left ? _Right : _Left;
}
_Left == _Right
라면 max
귀환_Left
하고 min
도 귀환_Left
한다.우리도 보자clang:
template <class _Tp, class _Compare>
_LIBCPP_NODISCARD_EXT inline
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
const _Tp&
min(const _Tp& __a, const _Tp& __b, _Compare __comp)
{
return __comp(__b, __a) ? __b : __a;
}
template <class _Tp, class _Compare>
_LIBCPP_NODISCARD_EXT inline
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11
const _Tp&
max(const _Tp& __a, const _Tp& __b, _Compare __comp)
{
return __comp(__a, __b) ? __b : __a;
}
본질적으로 같지만 이 예에서 원소가 같을 때 되돌아오기__a
는 MS에서 _Left
라고 부른다.따라서,clang과 MSVCC에 대해 입력이 같으면
min
와max
의 반환값은 같다.유일한 차이점은 첫 번째 입력을 되돌려 주고 두 번째 입력을 되돌려 주는 것이다.Gcc의 동작은 첫 번째 입력, 즉 왼쪽 입력을 되돌려 주는 딩동 소리와 유사하다.마이크로소프트가 다른 가치관을 선택한 이유가 무엇인지 궁금하다.
하지만 둘 다 이상한 사실을 바꿀 수는 없다.월터가 위원회에서 이 점을 제기했기 때문에 다른 사람들도 이를 구멍이라고 부른다.
만약 정말로 이것에 대해 곤란을 느끼고 min이 첫 번째 항목, max가 두 번째 항목으로 되돌아오기를 원한다면
std::minmax
을 사용할 수 있습니다. 왜냐하면 C++11이기 때문입니다.그것은 두 개의 요소가 필요하거나 항목 목록이 필요하지만, 우리의 예에서 두 개의 항목만 흥미롭다.
std::minmax
한 쌍을 되돌려줍니다. 첫 번째 항목은 최소 원소에 대한 상수 인용이고, 두 번째 항목은 최대 값입니다. 두 번째 입력이 같으면 첫 번째 입력이고, 두 번째 입력은 최대 값입니다.네, 이것은 사용
min
과max
를 모델링할 수 없음minmax
을 의미합니다.적어도 우리는 해결 방법이 있다.
결론
, Walter E Brown은
std::min
와 std::max
의 두 입력이 같으면 같은 값을 되돌려 주는 것이 정확하지 않다는 그의 의견에 동의했다.만약 이것이 너에게 매우 중요하다면, 너는 다른 해결 방법이 있다.원하는 방식으로 수동으로
min
및 max
를 수행할 수 있습니다.minmax
를 사용하거나 두 값을 같을 때 구분할 수 없는 비교 연산자를 사용할 수 있습니다.만약 당신이 코드에서 이 문제를 만났다면 저에게 알려 주세요.
더욱 깊이 연락하다
만약 당신이 이 문장을 좋아한다면,
subscribe to my newsletter
Reference
이 문제에 관하여(우리는 최소치와 최대치를 정확하게 계산했습니까?), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/sandordargo/do-we-correctly-calculate-min-and-max-4360텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)