반복자(Iterator)는 포인터와 유사한 객체로, 컨테이너에 저장된 요소들을 순회(iterate)하는 데 사용됩니다. 반복자를 사용하는 가장 큰 장점은 공통 인터페이스를 제공할 수 있다는 점입니다. 이를 통해 알고리즘이 컨테이너의 구체적인 구현 방식에 의존하지 않고 동작할 수 있습니다.
C++ 표준 라이브러리에는 다음과 같은 종류의 반복자가 정의되어 있습니다.
- 입력 반복자(Input Iterator)
- 출력 반복자(Output Iterator)
- 순방향 반복자(Forward Iterator)
- 양방향 반복자(Bidirectional Iterator)
- 임의 접근 반복자(Random Access Iterator)
이번 글에서 소개할 프로그램은 자료구조가 위의 반복자 중 어떤 유형을 사용하는지 확인하는 기능을 수행합니다.
반복자의 유형을 판별할 때 유용하게 활용할 수 있는 요소들은 다음과 같습니다.
- typeid: 실행 시간(runtime)에 타입 식별 정보를 반환합니다.
- iterator traits: 반복자가 가지는 속성(property)을 정의합니다.
- 반복자 카테고리(iterator category): 해당 반복자가 어느 범주에 속하는지 정의합니다.
예제 코드
#include <bits/stdc++.h>
using namespace std;
// 반복자의 카테고리를 문자열로 반환하는 함수
template <class T>
string iteratortype(T iterator){
if (typeid(typename iterator_traits<T>::iterator_category)
== typeid(input_iterator_tag))
return "Input";
else if (typeid(typename iterator_traits<T>::iterator_category)
== typeid(output_iterator_tag))
return "Output";
else if (typeid(typename iterator_traits<T>::iterator_category)
== typeid(forward_iterator_tag))
return "Forward";
else if (typeid(typename iterator_traits<T>::iterator_category)
== typeid(bidirectional_iterator_tag))
return "Bidirectional";
else if (typeid(typename iterator_traits<T>::iterator_category)
== typeid(random_access_iterator_tag))
return "Random_Access";
return "Missing";
}
int main(){
vector<int> vec;
auto iter = vec.begin();
cout << iteratortype(iter) << " Iterator\n";
return 0;
}실행 결과
Random_Access Iterator
코드 설명
위 코드는 iterator_traits<T>::iterator_category를 통해 반복자의 카테고리 태그를 가져온 뒤, typeid 연산자를 사용해 각 표준 태그(input_iterator_tag, output_iterator_tag, forward_iterator_tag, bidirectional_iterator_tag, random_access_iterator_tag)와 하나씩 비교합니다.
std::vector의 반복자는 메모리상 연속된 위치에 직접 접근할 수 있는 임의 접근 반복자(random access iterator)이므로, 실행 결과로 "Random_Access Iterator"가 출력됩니다. 같은 방식으로 list, set, map 등 다른 컨테이너의 반복자 유형도 손쉽게 확인할 수 있습니다.