54: TR1을 포함한 표준 라이브러리 구성요소와 편안한 친구가 되자
C++98에 명시되어 있는 표준 C++ 라이브러리의 주요 구성요소를 한 번 되짚어 보자.
- 표준 템플릿 라이브러리(Standard Template Library, STL)
- 컨테이너(vector, string, map 등), 반복자, 알고리즘(find, sort, transform 등), 함수 객체(less, greater 등) 외에 이런저런 컨테이너 어댑터와 함수 객체 어댑터(stack, priority_queue, mem_fun, not1 등)가 있다.
- iostream
- 사용자 정의 버퍼링, 국제화 기능이 가능한 입출력을 지원하며, 그 외에 cin, cout, cerr, clog 등의 사전정의 객체를 지원한다.
- 국제화 지원
- 수치 처리 지원
- 예외 클래스 계통
- 최상위 클래스인 exception 및 이것으로부터 갈라져 나온 파생 클래스들, 예를 들어 login_error 및 runtime_error 등이 여기에 포함된다.
- C89의 표준 라이브러리
TR1을 통해 명시된 새로운 구성요소는 총 14개이다. 모두 std네임스페이스에 들어 있는데, 정확히 말하면 std 안에 중첩된 tr1이란 네임스페이스에 들어 있다(std::tr1::). TR1의 구성요소를 정리해 보자.
- 스마트 포인터(smart pointer)
- tr1::shared_ptr, str1::weak_ptr이 여기에해당한다. 하나의 실체를 가리키는 자신과 같은 포인터의 개수를 유지해 놓는 똑똑한 포인터이다. 이런 기법을 가리켜 참조 카운팅(reference counting)이라고 부른다. 어떤 객체를 가리키는 최후의 스마트 포인터가 소멸될 때(즉, 참조 카운트가 0이될 때), 그 객체도 자동으로 삭제되는 것이다. 비순환형(acyclic) 자료구조 내의 자원 누출을 방지하는 용도에 아주 적합하다.
- 만약, 두 개 이상의 객체에 tr1::shared_ptr이 하나씩 들어 있고 각각의 tr1::shared_ptr이 이들 객체를 물고 있는 형태가 순환 구조를 이루고 있다면, 이 순환 구조 때문에 참조 카운트가 0이 되지 않을 수가 있다. 이런 상황을 막기 위해 쓰는 것이 tr1::weak_ptr이다. tr1::weak_ptr은 tr1::shared_ptr에 기반한 비순환형 자료구조에서 순환 고리를 가능하게 하는 포인터로 동작하게끔 설계되었다. 실제로 tr1::weak_ptr은 참조 카운트에는 가담하지 않는다. 어떤 객체를 물고 있는 마지막 tr1::shared_ptr이 소멸될 때, tr1::weak_ptr이 여전히 계속해서 그 객체를 가리키고 있더라도 그 객체는 삭제된다. 단, 이 경우의 tr1::weak_ptr은 무효상태(invalid)로 표시된다.
// 매개변수인 func는 std::string (int)와 호환되는 시그너처를 갖는 어떤 함수호출성 개체도 될 수 있다.
void registerCallback(std::tr1::function<std::string(int)> func);
- tr1::function
- 어떤 함수가 가진 시그너처와 호환되는 시그너처를 갖는 함수호출성 개체(callable entitiy)의 표현을 가능하게 해 주는 템플릿이다. 시그너처가 '비슷'하면 호출이 가능한 일반화 콜백 함수를 만들어 보자는 것이 주요 개념이다.
- 함수 시그너처 대신에 임의의 함수호출성 개체를 받도록 만들게 함으로써, int 타입 혹은 int로 변환이 가능한 어떤 타입도 전달받으며, string 타입 혹은 string으로 변환이 가능한 어떤 타입도 반환할 수 있는 그런 함수를 매개변수로 설정할 수 있다.
- tr1::bind
- 범용 바인더이다. TR1 이전의 바인더들과 달리, tr1::bind는 상수 멤버 함수 및 비상수 멤버 함수에 상관없이 동작한다. 또한 참조로 전달되는 매개변수에 대해서도 동작한다.
- 외부 보조 없이도 함수 포인터를 자체적으로 다룰 수 있기 때문에, tr1::bind를 호출하기 전에 ptr_fun, mem_fun 혹은 mem_fun_ref를 우겨 넣을 필요가 없다.
나머지 구성요소는 두 종류로 나눠서, 단독으로 딱딱 끊어지는 기능을 제공하는 종류부터 보자.
- 해시 테이블(hash table)
- 세트, 멀티세트, 맵, 멀티맵을 구현하는 데 이 해시 테이블이 쓰였다. TR1의 해시 기반 컨테이너의 특징 중 가장 인상적인 부분은 바로 이름이다. 각각, tr1::unordered_set, tr1::unordered_multiset, tr1::unordered_map, tr1::unordered_multimap이다. set, multiset, map, multimap에 저장되는 원소와 달리, TR1의 해시 기반 컨테이너는 원소가 저장되는 순서를 예측할 수 없다는 점을 강조하는 듯한 인상이 풍긴다.
- 정규 표현식(regular expression)
- 정규 표현식 기반의 탐색과 문자열에 대한 대체 연산이 가능하며, 일치되는 원소들 사이의 순회도 지원한다.
- 투플(tuple)
- pair 템플릿의 신세대 버전으로 pair와 달리 몇 개라도 담을 수 있다.
- tr1::array
- begin 및 end 등의 멤버 함수를 지원하는 배열이다. 객체의 크기는 컴파일 과정에서 고정되어 동적 메모리를 쓰지 않는다.
- tr1::mem_fn
- C++98의 mem_fun 및 mem_fun_ref를 그대로 안음과 동시에 기능을 확장
- tr1::reference_wrapper
- 기존의 참조자가 객체처럼 행사할 수 있도록 만들어 주는 템플릿으로, 무엇보다 이것을 사용하면 참조자를 담은 것처럼 동작하는 컨테이터를 만들 수 있다는 점이 가장 크다.
- 난수 발생
- rand 함수보다 몇 배는 우수한 난수 발생 기능이다.
- 특수 용도의 수학 함수
- 라게르(Laguerre) 다항식, 베셀(Bessel) 함수, 완전 타원 적분(complete elliptic integral) 등이며 그 외에도 많이 있다.
- C99 호환성 확장 기능
두 번째 부류는 더 세련된 템플릿 프로그래밍 기법, 이를테면 템플릿 메타프로그래밍(항목 48) 같은 기법을 지원하는 기술들이다.
- 타입 특성정보(type traits)
- 주어진 타입에 대한 컴파일 타임 정보를 제공하는 특성정보 클래스(항목 47 참조)의 모음이다.
- T라는 타입에 대해 T가 기본제공 타입인지, 가상 소멸자를 지원하는지, 공백 틀래스인지, 다른 U타입으로 암시적 변환이 가능한지 등의 정보를 들추어낼 수 있다. 적절한 바이트 정렬까지 잡아내준다.
- tr1::result_of
- 어떤 함수 호출의 반환 타입을 추론해 주는 템플릿이다.
TR1은 그저 표준 라이브러리에 대한 부가 구성요소일 뿐이다. TR1 이전의 것을 써서 만든 재래식 코드는 그대로 유효하다. 또한 TR1 자체는 그냥 문서일 뿐이다. 이 문서에 명시된 기능을 맛보려면, 문서의 내용을 실제로 구현한 코드를 구해야 한다. 그런 자료처 중 한 군데가 바로 부스트이다.
이것만은 잊지 말자!
- 최초에 상정된 표준 C++ 라이브러리의 주요 구성요소는 STL, iostream, 로케일 등이다. 여기에는 C89의 표준 라이브러리도 포함되어 있다.
- TR1이 도입되면서 추가된 것은 스마트 포인터(tr1::shared_ptr 등), 일반화 함수 포인터(tr1::function), 해시 기반 컨테이너, 정규 표현식 그리고 그 외의 10개 구성요소이다.
- TR1 자체는 단순히 명세서일 뿐이다. TR1의 기능을 사용하기 위해서는 명세를 구현한 코드를 구해야 한다. TR1 구현을 구할 수 있는 자료처 중 한 군데가 바로 부스트이다.
'C++ > Effective C++' 카테고리의 다른 글
[Effective C++] 55: Boo子有親! 부스트를 늘 여러분 가까이에 (1) | 2023.11.27 |
---|---|
[Effective C++] 53: 컴파일러 경고를 지나치지 말자 (1) | 2023.11.25 |
[Effective C++] 52: 위치지정 new를 작성한다면 위치지정 delete도 같이 준비하자 (0) | 2023.11.24 |
[Effective C++] 51: new 및 delete를 작성할 때 따라야 할 기존의 관례를 잘 알아 두자 (0) | 2023.11.22 |
[Effective C++] 50: new 및 delete를 언제 바꿔야 좋은 소리를 들을지를 파악해 두자 (1) | 2023.11.21 |