항목 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 반복자
    1. 입력 반복자
      • 전진만, 한칸씩만, 읽기만, 한번 읽기만
      • 읽기 전용 파일 포인터를 본떠서 만들어졌다.
      • ex) istream_iterator
    2. 출력 반복자
      • 전진만, 한칸씩만, 쓰기만, 한번 쓰기만
      • 쓰기 전용 파일 포인터를 본떠서 만들어졌다.
      • ex) ostream_iterator
    3. 순방향 반복자
      • 전진만, 한칸씩만, 읽기 / 쓰기, 여러번
      • ex) slist, TR1의 해시 컨테이너 등이 지원하는 반복자
    4. 양방향 반복자
      • 전후진, 한칸씩만, 읽기 / 쓰기, 여러번
      • ex) list, set, multiset, map, multimap 등이 지원하는 반복자
    5. 임의 접근 반복자
      • 양방향 반복자 + 반복자 산술 연산
      • 임의의 거리 이동을 상수 시간 안에 할 수 있다.
      • 기본 제공 포인터를 본떠서 만들었다.
      • vector, deque, string 등이 지원하는 반복자
  • 다섯개 반복자 범주 식별을 위한 태그 구조체가 존재한다.
  • 특성정보(traits) : 컴파일 도중 어떤 주어진 타입의 정보를 얻을 수 있게 해주는 객체를 지칭하는 개념 구현 기법이며 관례이다.
  • 특성정보는 기본타입 / 사용자 정의 타입 모두에서 돌아가야 한다.
    • 어떤 타입 내에 중첩된 정보 등으로는 구현이 안된다. (포인터의 경우 포인터 내부에 정보를 넣을 방법이 없다.)
  • 관례 1. 특성정보는 항상 구조체로 구현
  • 관례 2. 특성정보를 구현하는데 사용한 구조체를 특성정보 클래스라고 부른다.

  • 특성 정보 클래스 설계 및 구현 방법
    1. 다른 사람이 사용하도록 열어주고 싶은 타입 관련 정보를 확인한다.
    2. 그 정보를 식별하기 위한 이름을 선택한다.
    3. 지원하고자 하는 타입 관련 정보를 담은 템플릿 및 템플릿 특수화 버전을 제공한다.
  • 특성정보 클래스 사용법
    1. ‘작업자’ 역할을 맡을 함수 / 함수 템플릿을 특성정보 매개변수를 다르게 하여 오버로딩한다.(컴파일 시 체크하기 위해서) 그리고 전달되는 해당 특성정보에 맞춰서 각 오버로드 버전을 구현한다.
    2. 작업자를 호출하는 ‘주 작업자’ 역할을 맡을 함수 혹은 함수 템플릿을 만든다. 이 때 특성정보 클래스에서 제공하는 정보를 넘겨서 작업자를 호출하게 구현한다.