치춘짱베리굿나이스
[Rank 5] ft_containers - std::iterator_traits 본문
std::iterator_traits
namespace ft {
template <class Iter>
struct iterator_traits {
// template로 가져온 클래스에서의 :: 값은 typename으로 가져와야 한다
typedef typename Iter::difference_type difference_type;
typedef typename Iter::value_type value_type;
typedef typename Iter::pointer pointer;
typedef typename Iter::reference reference;
typedef typename Iter::iterator_category iterator_category; // iterator의 특성
};
뭐하는 친구인가요
반복자 특질
- 어떠한 알고리즘이든 컨테이너에서 동작할 때 이터레이터 (반복자) 를 사용하는데, 이때 반복자의 성질을 설명해주기 위한 구조체이다
- 알고리즘은 인자로 특정 컨테이너의 반복자를 넘겨받아도 이 반복자가 어떠한 특징을 가지고 있는지 알 수 없다
- 반복자의 특징을 정의한 구조체를 알고리즘 (또는 로직) 에 넘겨줌으로써 알고리즘이 모든 컨테이너 (임의의 컨테이너) 에 대해 동일하게 동작함을 보장한다고 볼 수 있다
- 이때 사용할 타입 정보를 담은 구조체가 바로 반복자 특질 (
iterator_traits
) 이다 - 사실 각 타입에 대한 별칭을 담고 있을 뿐, 특별한 기능이 있는 것은 아니다
Iter::difference_type
을 짧게difference_type
으로 줄인 느낌
각각에 대한 설명
difference_type
Iterator::difference_type
의 단축어이다
반복자와 반복자 간 간격을 표현한다 (메모리를 얼마만큼 건너뛸 것인지?)
value_type
Iterator::value_type
의 단축어이다
반복자가 가리키는 값의 타입을 나타낸다
pointer
Iterator::pointer
의 단축어이다
반복자가 가리키는 값의 포인터 타입을 나타낸다
reference
Iterator::reference
의 단축어이다
반복자가 가리키는 값의 참조 타입을 나타낸다
iterator_category
Iterator::category
의 단축어이다
반복자의 유형을 나타낸다
input_iterator_tag
- 입력 반복자에 대한 태그
- 입력만 가능하고, 쓰기가 불가능하므로 읽기 전용 알고리즘에서만 사용가능하다
- 증가 연산자 (
++
) 를 통한 일방통행만 가능하다 - 참조 연산자 (
*
) 를 통한 값 접근 및 읽어들이기가 가능하다
output_iterator_tag
- 출력 반복자에 대한 태그
- 입력 반복자와는 반대로 입력이 불가능하여 쓰기 전용 알고리즘에서만 사용 가능하다
- 증가 연산자 (
++
) 를 통한 일방통행만 가능하다 - 참조 연산자 (
*
) 를 통한 값 접근 및 쓰기가 가능하다
forward_iterator_tag
- 순방향 반복자에 대한 태그
- 입출력이 모두 가능하지만, 증가 연산자 (
++
) 를 통한 일방통행만 가능하다 - 입력 반복자와 출력 반복자를 합친 형태이며, 참조 연산자 (
*
) 를 이용하여 값 읽기 및 쓰기가 모두 가능하다
bidirectional_iterator_tag
- 양방향 반복자에 대한 태그
- 양방향 반복자는 순회할 때 전진, 후진이 모두 가능하다
- 전진은 위의 입출력 반복자와 마찬가지로 증가 연산자 (
++
) 를 사용하고, 후진은 반대로 감소 연산자 (—-
) 를 사용한다 - 순방향 반복자와 마찬가지로, 값 읽기 및 쓰기가 모두 가능하다
- 순방향 반복자에 후진 기능이 추가되었다고 생각하면 된다
random_access_iterator_tag
- 랜덤 액세스 반복자 (임의 접근 반복자) 에 대한 태그
- 랜덤 액세스에 관해서는 후술
- 첨자 연산자 (
[]
) 를 이용하여 임의의 원소에 접근 가능하다
포인터에 대한 특수화
template <class T>
struct iterator_traits<T*> { // 포인터 T* 특수화 => 랜덤 액세스 가능
typedef ptrdiff_t difference_type;
typedef T value_type;
typedef T* pointer;
typedef T& reference;
typedef std::random_access_iterator_tag iterator_category;
// 포인터 (배열) 쓸 때는 랜덤액세스이므로 랜덤액세스 반복자 태그 지정
};
- 템플릿이 포인터 타입일 경우, 랜덤 액세스를 지원하기 위해 멤버 타입을 다르게 정의한다
- 랜덤 액세스란? 어떠한 값에 접근하기 위해 다른 값들을 맨 앞부터 순차적으로 접근 (순차 액세스) 하는 것이 아니라, 특정 값에 바로 접근하는 방식이다
- 개포동을 가기 위해 선릉에서 한티 → 도곡 → 구룡 → 개포동을 거치는 것이 순차 액세스
- 개포동을 가기 위해 선릉에서 개포동으로 순간이동 하는 것이 랜덤 액세스
- 반복자를 기반으로 작성된 알고리즘을 포인터 값으로도 동작할 수 있도록 특수화한 것이다
difference_type
포인터 주소 간 차이를 나타내는 ptrdiff_t
가 들어간다
value_type
포인터가 가리키는 값 T
그 자체의 타입이 들어간다
pointer
템플릿 T
의 포인터가 들어간다
reference
템플릿 T의 참조가 들어간다
iterator_category
std::random_access_iterator_tag
를 넣는 이유는, 배열 포인터가 랜덤 액세스 방식으로 접근되기 때문에 이러한 형식으로 반복자를 사용한다는 것을 명시하는 것이다
참고 자료
'42 > 42s Cursus' 카테고리의 다른 글
[Rank 5] ft_containers - std::reverse_iterator (0) | 2023.01.17 |
---|---|
[Rank 5] ft_containers - explicit 키워드 (0) | 2023.01.13 |
[Rank 5] ft_irc - 만들어야 하는 명령어 정리 (3) | 2023.01.07 |
[Rank 5] ft_irc (작성중) (0) | 2023.01.07 |
[Rank 5] inception - Docker-compose (0) | 2022.10.26 |
Comments