Форум программистов, компьютерный форум CyberForum.ru

Использование пользовательского итератора для работы с STL алгоритмами: как определить typedef iterator_traits? - C++

Восстановить пароль Регистрация
 
Cynacyn
 Аватар для Cynacyn
33 / 33 / 0
Регистрация: 02.05.2013
Сообщений: 109
27.09.2013, 11:57     Использование пользовательского итератора для работы с STL алгоритмами: как определить typedef iterator_traits? #1
Здравствуйте! Есть класс итератора:
C++
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
33
34
typedef vector<char> Line;
 
//-------------------------------------------------------
 
class Text_iterator {
    list<Line>::iterator ln;
    list<Line>::const_iterator line_end; // end list<Line> line.cend();
    Line::iterator pos;
public:
    typedef forward_iterator_tag iterator_category; // подсмотрено в std::vector
 
    Text_iterator(list<Line>::iterator ll, Line::iterator pp, list<Line>::const_iterator _end)
        :   ln(ll), pos(pp), line_end(_end) {}
    
    char& operator*() { 
        return *pos; 
    }
    
    Text_iterator& operator++() {
        ++pos;
        if(pos==ln->end()) {
            ++ln;
            if(ln!=line_end) pos=ln->begin();
        }
        return *this;
    }
 
    bool operator==(const Text_iterator& other) const {
        return (ln==other.ln && pos==other.pos);
    }
    bool operator!=(const Text_iterator& other) const {
        return !(*this==other);
    }
};
остальной контекст использования итератора (немного кода), под спойлером:
Кликните здесь для просмотра всего текста
C++
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#include <iostream>
using std::istream;
 
#include <vector>
using std::vector;
 
#include <list>
using std::list;
 
#include <algorithm>
using std::find;
 
#include <iterator>
using std::forward_iterator_tag;
 
//-------------------------------------------------------
// helper; my realisation of advance
template<class Iter>
Iter advance(Iter p, int n) 
{
    if(!n) return p;
    while(n>0) { p++; n--; }
    while(n<0) { p--; n++; }
    return p;
}
 
//-------------------------------------------------------
 
typedef vector<char> Line;
 
//-------------------------------------------------------
 
class Text_iterator {
    list<Line>::iterator ln;
    list<Line>::const_iterator line_end; // end list<Line> line.cend();
    Line::iterator pos;
public:
    typedef forward_iterator_tag iterator_category;
 
    Text_iterator(list<Line>::iterator ll, Line::iterator pp, list<Line>::const_iterator _end)
        :   ln(ll), pos(pp), line_end(_end) {}
    
    char& operator*() { 
        return *pos; 
    }
    
    Text_iterator& operator++() {
        ++pos;
        if(pos==ln->end()) {
            ++ln;
            if(ln!=line_end) pos=ln->begin();
        }
        return *this;
    }
 
    bool operator==(const Text_iterator& other) const {
        return (ln==other.ln && pos==other.pos);
    }
    bool operator!=(const Text_iterator& other) const {
        return !(*this==other);
    }
};
 
//-------------------------------------------------------
 
struct Document {
    list<Line> line;
    
    Document() { line.push_back(Line()); }
    
    Text_iterator begin() {
        return Text_iterator(line.begin(), line.begin()->begin(), line.cend()); 
    }
    Text_iterator end() {
        //return Text_iterator(line.end(), line.end()->end());  // Expression: list iterator not dereferencable
    
        list<Line>::iterator last_line=line.begin();
        list<Line>::iterator it=line.begin();
        
        it++;
        for(; it!=line.end(); it++, last_line++);
                    
        return Text_iterator(line.end(), 
            last_line->end(), 
            line.cend()); 
    }
    
    bool empty() const
    {
        if(line.size()==1 && !line.begin()->size()) return true;
        else return false;
    }
};
 
//-------------------------------------------------------
 
istream& operator>>(istream& is, Document& d) 
{
    char ch;
    while(is.get(ch)) {
        d.line.back().push_back(ch);
        if(ch=='\n')
            d.line.push_back(Line());
    }
    return is;
}
 
//-------------------------------------------------------
 
void print(Document& d) 
{
    if(d.empty()) return;
    for(Text_iterator it=d.begin(); it!=d.end();++it)
        std::cout <<*it;
}
 
//-------------------------------------------------------
 
void erase_line(Document& d, int n) 
{
    if(d.empty() || n<0 || d.line.size()<=n) return;
    d.line.erase(advance(d.line.begin(), n));
}
 
//-------------------------------------------------------
 
bool match(Text_iterator first, Text_iterator last, const string& s)
{
    int i=0;
    for(Text_iterator it=first; it!=last && i<s.size(); it++, i++) 
        if(*it!=s[i]) return false;
    
    return true;
}
 
//-------------------------------------------------------
 
Text_iterator find_txt(Text_iterator first, Text_iterator last, const string& s)
{
    if(!s.size()) return last;
    char first_char=s[0];
    while(true) {
        Text_iterator p = find(first,last,first_char);
        if(p==last || match(p,last,s)) return p;
    }
}
 
//-------------------------------------------------------


при попытке использовать итераторы с std::find, компилятор начинает ругаться:
Кликните здесь для просмотра всего текста
C++
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
1>------ Построение начато: проект: EmptyConsole01, Конфигурация: Debug Win32 ------
1>  code.cpp
1>f:\projects\new\emptyconsole01\emptyconsole01\Document.h(121): warning C4018: <=: несоответствие типов со знаком и без знака
1>f:\projects\new\emptyconsole01\emptyconsole01\Document.h(130): warning C4018: <: несоответствие типов со знаком и без знака
1>f:\projects\new\emptyconsole01\emptyconsole01\Document.h(130): warning C4620: не найдена постфиксная форма "operator ++" для типа "Text_iterator"; используется префиксная форма
1>          f:\projects\new\emptyconsole01\emptyconsole01\Document.h(33): см. объявление "Text_iterator"
1>f:\VSE2010\VC\include\xutility(386): error C2039: value_type: не является членом "Text_iterator"
1>          f:\projects\new\emptyconsole01\emptyconsole01\Document.h(33): см. объявление "Text_iterator"
1>          f:\VSE2010\VC\include\xutility(740): см. ссылку на создание экземпляров класса шаблон при компиляции "std::iterator_traits<_Iter>"
1>          with
1>          [
1>              _Iter=Text_iterator
1>          ]
1>          f:\VSE2010\VC\include\algorithm(72): см. ссылку на создание экземпляров функции шаблон при компиляции "void std::_Debug_range<_InIt>(_InIt,_InIt,std::_Dbfile_t,std::_Dbline_t)"
1>          with
1>          [
1>              _InIt=Text_iterator
1>          ]
1>          f:\projects\new\emptyconsole01\emptyconsole01\Document.h(143): см. ссылку на создание экземпляров функции шаблон при компиляции "_InIt std::find<Text_iterator,char>(_InIt,_InIt,const _Ty &)"
1>          with
1>          [
1>              _InIt=Text_iterator,
1>              _Ty=char
1>          ]
1>f:\VSE2010\VC\include\xutility(386): error C2146: синтаксическая ошибка: отсутствие ";" перед идентификатором "value_type"
1>f:\VSE2010\VC\include\xutility(386): error C4430: отсутствует спецификатор типа - предполагается int. Примечание. C++ не поддерживает int по умолчанию
1>f:\VSE2010\VC\include\xutility(386): error C2602: std::iterator_traits<_Iter>::value_type не является членом базового класса "std::iterator_traits<_Iter>"
1>          with
1>          [
1>              _Iter=Text_iterator
1>          ]
1>          f:\VSE2010\VC\include\xutility(386): см. объявление "std::iterator_traits<_Iter>::value_type"
1>          with
1>          [
1>              _Iter=Text_iterator
1>          ]
1>f:\VSE2010\VC\include\xutility(386): error C2868: std::iterator_traits<_Iter>::value_type: недопустимый синтаксис для "using"-объявления; требуется полное имя
1>          with
1>          [
1>              _Iter=Text_iterator
1>          ]
1>f:\VSE2010\VC\include\xutility(387): error C2039: difference_type: не является членом "Text_iterator"
1>          f:\projects\new\emptyconsole01\emptyconsole01\Document.h(33): см. объявление "Text_iterator"
1>f:\VSE2010\VC\include\xutility(387): error C2146: синтаксическая ошибка: отсутствие ";" перед идентификатором "difference_type"
1>f:\VSE2010\VC\include\xutility(387): error C4430: отсутствует спецификатор типа - предполагается int. Примечание. C++ не поддерживает int по умолчанию
1>f:\VSE2010\VC\include\xutility(387): error C2602: std::iterator_traits<_Iter>::difference_type не является членом базового класса "std::iterator_traits<_Iter>"
1>          with
1>          [
1>              _Iter=Text_iterator
1>          ]
1>          f:\VSE2010\VC\include\xutility(387): см. объявление "std::iterator_traits<_Iter>::difference_type"
1>          with
1>          [
1>              _Iter=Text_iterator
1>          ]
1>f:\VSE2010\VC\include\xutility(387): error C2868: std::iterator_traits<_Iter>::difference_type: недопустимый синтаксис для "using"-объявления; требуется полное имя
1>          with
1>          [
1>              _Iter=Text_iterator
1>          ]
1>f:\VSE2010\VC\include\xutility(389): error C2039: pointer: не является членом "Text_iterator"
1>          f:\projects\new\emptyconsole01\emptyconsole01\Document.h(33): см. объявление "Text_iterator"
1>f:\VSE2010\VC\include\xutility(389): error C2146: синтаксическая ошибка: отсутствие ";" перед идентификатором "pointer"
1>f:\VSE2010\VC\include\xutility(389): error C4430: отсутствует спецификатор типа - предполагается int. Примечание. C++ не поддерживает int по умолчанию
1>f:\VSE2010\VC\include\xutility(389): error C2602: std::iterator_traits<_Iter>::pointer не является членом базового класса "std::iterator_traits<_Iter>"
1>          with
1>          [
1>              _Iter=Text_iterator
1>          ]
1>          f:\VSE2010\VC\include\xutility(389): см. объявление "std::iterator_traits<_Iter>::pointer"
1>          with
1>          [
1>              _Iter=Text_iterator
1>          ]
1>f:\VSE2010\VC\include\xutility(389): error C2868: std::iterator_traits<_Iter>::pointer: недопустимый синтаксис для "using"-объявления; требуется полное имя
1>          with
1>          [
1>              _Iter=Text_iterator
1>          ]
1>f:\VSE2010\VC\include\xutility(390): error C2039: reference: не является членом "Text_iterator"
1>          f:\projects\new\emptyconsole01\emptyconsole01\Document.h(33): см. объявление "Text_iterator"
1>f:\VSE2010\VC\include\xutility(390): error C2146: синтаксическая ошибка: отсутствие ";" перед идентификатором "reference"
1>f:\VSE2010\VC\include\xutility(390): error C4430: отсутствует спецификатор типа - предполагается int. Примечание. C++ не поддерживает int по умолчанию
1>f:\VSE2010\VC\include\xutility(390): error C2602: std::iterator_traits<_Iter>::reference не является членом базового класса "std::iterator_traits<_Iter>"
1>          with
1>          [
1>              _Iter=Text_iterator
1>          ]
1>          f:\VSE2010\VC\include\xutility(390): см. объявление "std::iterator_traits<_Iter>::reference"
1>          with
1>          [
1>              _Iter=Text_iterator
1>          ]
1>f:\VSE2010\VC\include\xutility(390): error C2868: std::iterator_traits<_Iter>::reference: недопустимый синтаксис для "using"-объявления; требуется полное имя
1>          with
1>          [
1>              _Iter=Text_iterator
1>          ]
========== Построение: успешно: 0, с ошибками: 1, без изменений: 0, пропущено: 0 ==========

Насколько я понял, нужно опеределить эти typedef'ы iterator_traits:
difference_type
value_type
pointer
reference
iterator_category
Но походу обучения я работал с ними очень поверхностно, по идее автор учебника подразумавает что код должен работать и так (или это такое датское коварство). Помогите пожалуйста.
Заранее спасибо.

Добавлено через 7 минут
Пока что определил так.
C++
1
2
3
4
5
    typedef forward_iterator_tag iterator_category;
    typedef ptrdiff_t difference_type;
    typedef char value_type;
    typedef char* pointer;
    typedef char& reference;
Компилируется работает.
Думаю тему можно закрывать.
Спасибо за внимание.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
27.09.2013, 11:57     Использование пользовательского итератора для работы с STL алгоритмами: как определить typedef iterator_traits?
Посмотрите здесь:

Удаление элементов вектора с использованием итератора в STL C++
C++ Удаление елемента списка с использованием итератора. STL
C++ Использование потокового итератора для пользовательских обьектов
C++ Использование итератора в двусвязном списке
Использование Typedef C++
C++ Какую функцию STL использовать для работы с множеством ?
Сохранение данных пользовательского типа в list из stl C++
C++ Использование list stl для вывода в файл

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Ответ Создать тему
Опции темы

Текущее время: 13:36. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru