[Effective C++] 항목 45 ~ 47
항목 45 : “호환되는 모든 타입”을 받아들이는데는 멤버 함수 템플릿이 직방!
-
포인터에서 스마트 포인터로 대신할 수 없는 특징 : 암시적 변환 지원
- 멤버 함수 템플릿 : 어떤 클래스의 멤버 함수를 찍어내는 템플릿
- 일반화 복사 생성자 : 같은 템플릿을 써서 인스턴스화 되지만 타입이 다른 타입의 객체로부터 원하는 객체를 만들어주는 생성자
- ex)
template<typename T> classs SmartPtr { public: template<typename U> smartPtr(const SmartPtr<U>& other); }
- 템플릿으로 일반화 복사 생성자 구현 시 상속의 의미를 역행하는 변환까지 해줘서 곤란하다.
- ex) 멤버 초기화 리스트로 데이터 멤버 T* 타입 포인터를 내부 멤버 함수 템플릿 U* 타입의 포인터로 초기화
- U에서 T로 암시적 변환이 가능할 때만 컴파일 에러가 나지 않는다.
- ex) 다른 예 : 대입 연산자
- shared_ptr 클래스 템플릿은 호환되는 모든 기본 제공 포인터 shared_ptr, auto_ptr, weak_ptr 객체들로부터 생성자 호출이 가능하고 weak_ptr을 제외한 나머지를 대입 연산에 쓸 수 있다.
- 멤버 함수 템플릿이 C++언어의 기본 규칙까지 바꾸진 않는다.
- 일반화 복사 생성자를 어떤 클래스 안에 선언하는 것은 컴파일러가 나름의 복사 생성자(비템플릿)을 만드는 것을 막는 요소가 아니다.
항목 46 : 타입 변환이 바람직할 경우에는 비멤버 함수를 클래스 템플릿 안에 정의해두자.
- 템플릿 인자 추론 과정에서는 암시적 타입 변환이 고려되지 않는다.
- 클래스 템플릿 안에 프랜드 함수를 넣어 두면 함수 템플릿으로서의 성격을 주지 않고 특정한 함수 하나를 나타낼 수 있다는 사실을 이용하여 해결이 가능하다.
- 클래스 템플릿 내부에서는 템플릿의 이름(<>를 뗀 것)을 그 템플릿 및 매개변수의 줄임말로 쓸 수 있다.
- 호출 시 상황에 맞는 함수를 자동으로 인스턴스화 하기 위해서는 그 비멤버 함수를 클래스 안에 선언해야 하고, 클래스 안에 비멤버 함수를 선언하는 유일한 방법이 ‘프렌드’. private 멤버 접근과는 상관 없이 사용 가능하다.
- 클래스 바깥에서 정의된 도우미 함수만 호출하는 식으로 암시적 인라인 선언의 영향을 최소화 할 수 있다. -> 프렌드 함수는 도우미만 호출하게 하기
- 도우미 함수 : 실 기능이 구현된 함수
- 프렌드 함수는 도우미만 호출하게 만들기 방법
항목 47 : 타입에 대한 정보가 필요하다면 특성 정보 클래스를 사용하자
- STL : 컨테이너, 반복자, 알고리즘, 유틸리티
- STL 반복자
- 입력 반복자
- 전진만, 한칸씩만, 읽기만, 한번 읽기만
- 읽기 전용 파일 포인터를 본떠서 만들어졌다.
- ex) istream_iterator
- 출력 반복자
- 전진만, 한칸씩만, 쓰기만, 한번 쓰기만
- 쓰기 전용 파일 포인터를 본떠서 만들어졌다.
- ex) ostream_iterator
- 순방향 반복자
- 전진만, 한칸씩만, 읽기 / 쓰기, 여러번
- ex) slist, TR1의 해시 컨테이너 등이 지원하는 반복자
- 양방향 반복자
- 전후진, 한칸씩만, 읽기 / 쓰기, 여러번
- ex) list, set, multiset, map, multimap 등이 지원하는 반복자
- 임의 접근 반복자
- 양방향 반복자 + 반복자 산술 연산
- 임의의 거리 이동을 상수 시간 안에 할 수 있다.
- 기본 제공 포인터를 본떠서 만들었다.
- vector, deque, string 등이 지원하는 반복자
- 입력 반복자
- 다섯개 반복자 범주 식별을 위한 태그 구조체가 존재한다.
- 특성정보(traits) : 컴파일 도중 어떤 주어진 타입의 정보를 얻을 수 있게 해주는 객체를 지칭하는 개념 구현 기법이며 관례이다.
- 특성정보는 기본타입 / 사용자 정의 타입 모두에서 돌아가야 한다.
- 어떤 타입 내에 중첩된 정보 등으로는 구현이 안된다. (포인터의 경우 포인터 내부에 정보를 넣을 방법이 없다.)
- 관례 1. 특성정보는 항상 구조체로 구현
-
관례 2. 특성정보를 구현하는데 사용한 구조체를 특성정보 클래스라고 부른다.
- 특성 정보 클래스 설계 및 구현 방법
- 다른 사람이 사용하도록 열어주고 싶은 타입 관련 정보를 확인한다.
- 그 정보를 식별하기 위한 이름을 선택한다.
- 지원하고자 하는 타입 관련 정보를 담은 템플릿 및 템플릿 특수화 버전을 제공한다.
- 특성정보 클래스 사용법
- ‘작업자’ 역할을 맡을 함수 / 함수 템플릿을 특성정보 매개변수를 다르게 하여 오버로딩한다.(컴파일 시 체크하기 위해서) 그리고 전달되는 해당 특성정보에 맞춰서 각 오버로드 버전을 구현한다.
- 작업자를 호출하는 ‘주 작업자’ 역할을 맡을 함수 혹은 함수 템플릿을 만든다. 이 때 특성정보 클래스에서 제공하는 정보를 넘겨서 작업자를 호출하게 구현한다.