블로그 이미지
Every unexpected event is a path to learning for you.

카테고리

분류 전체보기 (2309)N
Unity3D (565)N
Programming (471)N
Unreal (4)
Gamebryo (56)
Tip & Tech (182)
협업 (34)
3DS Max (3)
Game (12)
Utility (114)
Etc (92)
Link (31)
Portfolio (19)
Subject (90)
iOS,OSX (37)
Android (12)
Linux (5)
잉여 프로젝트 (2)
게임이야기 (1)
Memories (19)
Interest (37)
Thinking (36)
한글 (26)
PaperCraft (5)
Animation (408)
Wallpaper (2)
재테크 (19)
Exercise (3)
나만의 맛집 (2)
냥이 (9)
육아 (5)
Total1,332,748
Today13
Yesterday299
Statistics Graph

달력

« » 2019.10
    1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31    

공지사항

태그목록

내가 STL에 조예가 깊어서 글을 남기는 것이 아니라, Effecitve STL 을 공부하는 사람들이 이 글을 보고, 도움이 되었으면 하는 생각과, 혹시 내가 틀린것이 있다면 지적해 주시지 않을까 란 생각으로 글을 올리는것임을 미리 밝힙니다.  - 최익필

저번 26항목에서 각 iterator 간의 변환 과정을 그림(?) 으로 보여 주었었다.

              const_iterator
         ↗                       ↖
iterator                              ↖  base()
         ↘↖base()                   ↖
              reverse_iterator    →   const_reverse_iterator


다시 정리 하자면,
1. 화살표 방향은 컴파일러에 의해서 암시적으로 바뀐다.(안그런 컴파일러도 있으니 해결방법은 26항목)
2. base() 는 함수이고, 명시적으로 사용자가 호출해야지만, 변환이 가능하다는 것이다.

여기서 잠깐,
혹시 iterator 를 casting 하면 되지 않을까? 란 생각을 했다면, 아직 iterator 가 어떻게 구현되었는지 분석하지 않은듯 보이는데, iterator는 .. class객체이며, 각 iterator 마다 각기 다른 class 이다. 그렇기 때문에 cating 을 해도 정상 작동하지 않는다.

본론으로 들어와서.. const_iterator ---> iterator 방향으로 변환이 되지 않는데, 어떻게 저자는 바꿀수 있다고 할수 있는가?
그 꽁수가 distance 함수와 advance 함수를 사용하는것이다. 아래 코드도 포함한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
// ikpil.com or ikpil.tistory.com
// MSVC2005 distance 내부
template<class _InIt> inline
    typename iterator_traits<_InIt>::difference_type
    __CLRCALL_OR_CDECL distance(_InIt _First, _InIt _Last)
{   // return distance between iterators
    // typename 잘 썻고~ Off 선언하고~
    typename iterator_traits<_InIt>::difference_type _Off = 0;
    // 두 인자 사이의 거리를 Off에 기록 하고
    _Distance2(_First, _Last, _Off, _Iter_cat(_First));
    // Off 리턴~
    return (_Off); 
}

즉 두 같은 타입의 두 iterator를 받아 드리어, 그 사이를 리턴해 준다.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// ikpil.com or ikpil.tistory.com
// MSVC2005 advance 내부
template<class _InIt,
class _Diff> inline
    void __CLRCALL_OR_CDECL advance(_InIt& _Where, _Diff _Off)
{   // increment iterator by offset, arbitrary iterators
    // 레퍼런스로 받은 Where 을 다시 _Advace에 넣는다.
    _Advance(_Where, _Off, _Iter_cat(_Where));
}
// MSVC2005 _Advance 내부
template<class _InIt,
class _Diff> inline
    void __CLRCALL_OR_CDECL _Advance(_InIt& _Where, _Diff _Off, input_iterator_tag)
{   // increment iterator by offset, input iterators
 
#if _HAS_ITERATOR_DEBUGGING
    //  if (_Off < 0)
    //      _DEBUG_ERROR("negative offset in advance");
#endif /* _HAS_ITERATOR_DEBUGGING */
 
    for (; 0 < _Off; --_Off)
        // &로 받은 .. Where을 전위연산하여 Off 만큼 증가 시킨다.
        ++_Where;
}

std::advace()의 인자값으러 넣은 iterator를 Off 길이 만큼 이동 시켜 준다.


자.. 두 함수의 설명은 끝났고. 이제 이 두 함수를 이용하여, const_iterator 를 iterator 로 변환해 보자. 주의해야 할것은 std::distance 는 한가지 타입의 iterator만 받는 템플릿 함수이므로 그냥 호출하면 const_iterator 를 iterator 로 변환을 시도하여, 컴파일타임 에러를 발생시킬 것이다.


그래서 명시적으로 const_iterator 라고 알려 주기만 하면 된다. 그래서 아래의 코드처럼 하면 iterator 로 변환 완료!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// ikpil.com or ikpil.tistory.com
 
#include <deque>
#include <algorithm>
#include <iostream>
 
typedef std::deque<int> Container;
 
int main( void )
{
    Container Test;
     
    Test.push_back(1);
    Test.push_back(1);
    Test.push_back(1);
    Test.push_back(1);
 
    typedef Container::const_iterator Const_It;
    Const_It cit = Test.end(); // 끝을 가리키게 한다.
 
    typedef Container::iterator Nomal_It;
    Nomal_It it = Test.begin(); // 꼭 초기화를 해줘야 한다.
     
     
    // distance 는 템플릿 함수이므로 명시적으로 지정 가능하다.
    std::advance(it, std::distance<Const_It>(it, cit));
 
    if( cit == it )    // <-- 왜 cit 을 먼저 썻는지 알 것이다.
        std::cout << "같습니다." << std::endl;
    else
        std::cout << "다릅니다.." << std::endl;
}


그런데 눈치 빠른 분들은 이런 생각을 하게 될 것이다. "이거 쓸때 없는 비용 많이 무는거 같은데..? 거리가 멀면 멀어질수록 더 느려지잖아?" .. 맞다. 역시 당신은 똑똑했다.  그래서 const_iterator 보다 iterator 를 사용하라고 26장에서 설명했던 것이다.


이것 만은 잊지 말자.
1. const_iterator 를 iterator 로 바꿀수 있다!
2. 대신 좀 시간이 걸린다. 속편히 iterator 를 사용하는것을 염두하자.


관련링크
http://lagoons.net/tt/594 <-- 깔끔한 설명
http://alones.kr/blog/626?TSSESSIONaloneskrblog=1e73a3a9327170d3301688495e6aeb41 <-- 다른 경우


Posted by blueasa

댓글을 달아 주세요