std::copy, std::transform, etc...
대부분의 Dest의 Iterator를 받는 알고리즘들은 그 컨테이너가 공간 요소를 넣기에 충분한 용량 ( capacity ) 를 확보하길 요구한다.
하지만 얼마나 들어올지 모르는 상황에서 컨테이너에 대한 reserve를 할 수 없으니, 반복자 어댑터를 사용하는걸 추천한다.
std::copy, std::transform 같은 알고리즘들은 밑과 같이 작성되어 있다.
template<class InputIt, class OutputIt> OutputIt copy(InputIt first, InputIt last, OutputIt d_first) { while (first != last) { *d_first++ = *first++; } return d_first; }
iterator 의 operator= 를 통해 복사 또는 연산을 지원하는데, 반복자 어댑터는 이 iterator의 operator= 를
operator overloading 하여 내부에서 해당 컨테이너의 push 연산을 호출한다.
template<class _Container> class back_insert_iterator : public _Outit { // wrap pushes to back of container as output iterator public: explicit back_insert_iterator(_Container& _Cont) : container(&_Cont) { // construct with container } back_insert_iterator<_Container>& operator=( typename _Container::const_reference _Val) { // push value into container container->push_back(_Val); // back_insert_iterator 는 container 내의 push_back을 호출 return (*this); } protected: _Container *container; // pointer to container };
inserter(), back_inserter(), front_inserter() 는 각각
insert_iterator, back_insert_iterator, front_insert_iterator 를 생성한다.
물론 Container에 맞는 iterator adaptor function을 호출하여야 한다.
inserter()는 내부에서 해당 컨테이너의 insert 함수를 호출한다.
insert_iterator& operator=(typename _Container::value_type&& _Val) { // push value into container iter = container->insert(iter, _STD move(_Val)); ++iter; return (*this); }
std::list<int> list1{ 1,2,3,4,5 }; std::list<int> examlist1; std::copy(list1.begin(), list1.end(), std::back_inserter(examlist1)); // 1, 2, 3, 4, 5 -> 내부에선 push_back을 호출함 std::list<int> examlist2; std::copy(list1.begin(), list1.end(), std::front_inserter(examlist2)); // 5, 4, 3, 2, 1 -> 내부에선 push_front를 호출함 std::list<int> examlist3; std::copy(list1.begin(), list1.end(), std::inserter(examlist3, examlist3.begin())); // 1, 2, 3, 4, 5 -> 내무에선 examlist3.insert(list1.begin(), list1.begin() +1... 이 될 것)
물론 inserter 같은 function이 아닌, iterator 자체를 만들어 넣어줄 수도 있다.
std::list<int> examlist4; std::copy(list1.begin(), list1.end(), std::back_insert_iterator<std::list<int>>(examlist4)); std::list<int> examlist5; std::copy(list1.begin(), list1.end(), std::insert_iterator<std::list<int>>(examlist4, examlist4.begin()));
모든 inserter_iterator 들은 nothrow 하다.
'C++ > STL' 카테고리의 다른 글
STL) 나만의 Allocator( 할당자 ) 만들기 - 1 (0) | 2019.04.16 |
---|---|
std::list::splice (0) | 2019.04.12 |
STL) 분할, 정렬, 힙에 대한 추가 연산들 (stable_*, is_*, is_*_until) (0) | 2019.02.20 |
STL) 순열(permutation)과 관련된 함수들 (std::next_permutation, std::prev_permutation, std::rotate, std::shuffle) (0) | 2019.02.20 |
STL) 파티션에 대한 함수들 ( std::partition, std::stable_partition, std::partition_point ) (0) | 2019.02.19 |