일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 언리얼
- 비교 함수 객체
- 티스토리챌린지
- UE4
- Vector
- resource management class
- virtual function
- effective stl
- 루아
- 암시적 변환
- lua
- 오블완
- c++
- implicit conversion
- 메타테이블
- 스마트 포인터
- 참조자
- 다형성
- Smart Pointer
- 게임
- exception
- operator new
- more effective c++
- 상속
- Effective c++
- 영화 리뷰
- 반복자
- reference
- 예외
- 영화
Archives
- Today
- Total
스토리텔링 개발자
[Effective STL] 42. less<T> 본문
728x90
항목 42. less<T>는 operator<의 의미임을 꼭 알아두자
less<T>의 기본 동작
- 아래처럼 기본적으로 무게로 정렬되는 Widget이 있다.
class Widget
{
public:
...
size_t weight() const;
size_t maxSpeed() const;
// 무게로 정렬되는 operator<
bool operator<(const Widget& lhs, const Widget& rhs)
{
return lhs.weight() < rhs.weight();
}
};
- 헌데, 최대 속도(maxSpeed)를 가지고 정렬하는 multiset<Widget>을 만들고 싶다면?
- multiset<Widget>의 기본 비교 함수는 less<Widget>이다.
- 하지만, less<Widget>은 기본적으로 Widget 객체 두 개에 대해 operator<를 호출하여 동작한다.
문제 해결하기(잘못된 예)
- 템플릿 특수화로 less<Widget>과 operator<의 관계를 끊어버린다.
// 템플릿 특수화로 처리한다.
template<>
struct std::less<Widget>
{
bool operator()(const Widget& lhs, const Widget& rhs) const
{
return lhs.maxSpeed() < rhs.maxSpeed();
}
};
- 일반적으로 std 내의 STL 컴포넌트를 수정하는 일은 금지되어 있다.
- 하지만 일부 경우에는 약간의 처리(tinkering)은 허용된다.
- 사용자 정의 타입에 대해서는 std 템플릿을 조정해서 한정할 수 있다.
- 그래서 위 코드는 컴파일 에러가 발생하지 않는다.
- STL 컴포넌트를 수정해야 하는 상황 예시(C++98 한정)
-
// shared_ptr이 표준이 아니었을 때는 이런 처리가 필요했다. namespace std { tempalte<typename T> struct less<shared_ptr<T>> { bool operator()(const shared_ptr<T>& a, const shared_ptr<T>& b) const { // 단지 less에 T*가 들어왔을 때처럼 동작하게 래핑했을 뿐이다. return less<T*>()(a.get(), b.get()); } } }
- 기본적으로 사용자는 less가 operator<와 동일한 동작을 하는 것으로 기대한다.
- 하지만 템플릿 특수화 버전은 그걸 가볍게 무시해버리며, 직관성이 무너진다.
multiset<Widget> widgets; // 누가 봐도 operator<로 정렬될 것 같지만....
// 템플릿 특수화 버전의 less로 정렬됨을 추론할 수가 없다.
직관적으로 문제 해결하기
- less 이외의 함수 객체로 비교를 수행하게 한다.
struct MaxSpeedCompare
{
bool operator()(const Widget& lhs, const Widget& rhs) const
{
return lhs.maxSpeed() < rhs.maxSpeed();
}
};
multiset<Widget, MaxSpeedCompare> widgets; // 비교를 수행할 함수 객체를 사용하여 선언
- 람다를 사용할 수도 있다.
// 물론 람다를 사용할 수도 있다.
auto compare = [](const Widget& lhs, const Widget& rhs)
{
return lhs.maxSpeed() < rhs.maxSpeed();
};
multiset<Widget, decltype(compare)> widgets(compare); // 인자로 람다를 넘겨줘야 한다.
728x90
'개발 > Effective STL' 카테고리의 다른 글
[Effective STL] 44. 같은 이름의 멤버 함수 vs 알고리즘 (0) | 2025.01.14 |
---|---|
[Effective STL] 43. 루프보단 알고리즘 (0) | 2025.01.13 |
[Effective STL] 41. ptr_fun, mem_fun, mem_fun_ref(C++98) (0) | 2025.01.09 |
[Effective STL] 40. adaptable한 함수 객체(C++98) (0) | 2025.01.08 |
[Effective STL] 39. predicate는 순수 함수일 것 (0) | 2025.01.07 |
Comments