Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
ninja2
231 / 187 / 7
Регистрация: 26.09.2012
Сообщений: 2,018
Завершенные тесты: 1
#1

Checked_iter - C++

25.07.2013, 04:13. Просмотров 1001. Ответов 23
Метки нет (Все метки)

Здорова господа!
Я тут пытаюсь создать свой Checked_iter, вот код который из книги набрал вроде кое-как работает:
Кликните здесь для просмотра всего текста
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
//Chacked_iter
#include <iostream>
using std::cout;
using std::endl;
using std::cerr;
#include <list>
using std::list;
#include <string>
using std::string;
#include <vector>
using std::vector;
#include <iterator>
using std::iterator_traits;
 
struct out_of_bounds{};
 
template<class Cont,class Iter=typename Cont::iterator>
class Checked_iter : public iterator_traits<Iter>//наследует все типы итераторов
{
public:
    Iter curr;//итератор для текущей позиции
    Cont* c;//указатель на текущий элемент
    //...
 
    void valid(Iter p)const
    {
        if(c->end()==p)return;//если конец, то возврат
        for(Iter pp=c->begin();pp!=c->end();++pp) if(pp==p)return;//если pp=p, то елемент найден возврат
        throw out_of_bounds();//элемент не находится в последовательности выход
    }
 
    //оператор сравнения
    friend bool operator==(const Checked_iter& i,const Checked_iter& j)
    {
        return i.c==j.c&&i.curr==j.curr;
    }
 
    //нет умолчательного инициализатора (конструктора по умолчанию)
    //конструктор предобразования
    Checked_iter(Cont& x, Iter p) :c(&x),curr(p){valid(p);}
    //конструктор копирования
    Checked_iter(Cont& x) :c(&x),curr(x.begin()){}
 
    //операция разыменования
    reference operator*()const
    {
        if(curr==c->end())throw out_of_bounds();//еси текущий элемент равен консу, то генерация выхода за границы
        return *curr;//если не равен, то возврат значения по ссылке
    }
 
    //доступ через указатель
    pointer operator->() const
    {
        if(curr==c->end())throw out_of_bounds();//если текущий элемент равен концу, то генерация выхода за границы
        return &*curr;//возврат указателя на элемент
    }
 
    //операция '+'
    Checked_iter operator+(difference_type d)const//только для итераторов произвольного доступа
    {
        //тут похоже какието действия с указателями
        //если указатель на конец минус текущий указатель меньше d
        if(c->end()-curr<d||d<-(curr-c->begin()))throw out_of_bounds();
        return Checked_iter(c,curr+d);
    }
 
    reference operator[](difference_type d)const//только для итераторов произвольного доступа
    {
        if(c->end()-curr<=d||d<-(curr-c->begin()))throw out_of_bounds();
        return curr[d];
    }
 
    Checked_iter operator++ ()//префиксный ++
    {
        if(curr==c->end())throw out_of_bounds();
        ++curr;
        return *this;
    }
 
    Checked_iter operator++(int)//постфиксный ++
    {
        Checked_iter tmp=*this;
        ++*this;//проверяется префиксным ++
        return tmp;
    }
 
    Checked_iter operator--()//префиксный
    {
        if(curr==c->begin())throw out_of_bounds();
        --curr;
        return *this;
    }
 
    Checked_iter operator--(int)//постфиксный --
    {
        Checked_iter tmp=*this;
        --*this;//проверяется префиксным --
        return tmp;
    }
 
    difference_type index()const {return curr-c->begin();}//только произвольный доступ
    Iter unchecked() const {return curr;}
    //+,-,< и т.д.(параграф 19.6[6])
};
 
int main()
{
    cout <<"Chacked_iter"<<endl;
    list<string> ls;
    ls.push_back("hellow");
    ls.push_back("world");
 
    Checked_iter<list<string> > p(ls,ls.begin());
    try
    {
        cout <<*p<<endl;
        ++p;
        cout <<*p<<endl;
        ++p;
        cout <<*p<<endl;
    }
    catch(out_of_bounds)
    {
        cout <<"event be except"<<endl;
    }
 
    return 0;
}


И тут повозникало немножко вопросов:
C++
1
2
3
4
5
reference operator[](difference_type d)const//только для итераторов произвольного доступа
    {
        if(c->end()-curr<=d||d<-(curr-c->begin()))throw out_of_bounds();
        return curr[d];
    }
Вот этот кусок кода не сильно понятен. Вот что такое difference_type???? Я так думаю это какой то typedef из iterator_traits, да и вообще что такое iterator_traits???? Это я как бы понял если мы наследуем от iterator, то мы указываем одну из категорий итераторов, а когда от iterator_traits???? Он просто на фонарь сам определяет какой у нас итератор? То есть как бы содержит в себе все типы итераторов.

Вот эта строчка несильно понятна
C++
1
2
if(c->end()-curr<=d||d<-(curr-c->begin()))throw out_of_bounds();
        return curr[d];
с->end()-curr тут вроде ясно должно вернутся int да и вообще не ясно что будет если от конца последовательности отнять текущий итератор? Я знаю что будет если от итератора который указывает допустим на третий элемент отнять указатель на начало, то вернется 2 (или 3).

Еще вот эта вот штуковина
C++
1
struct out_of_bounds{};
Это я уже сам ее определил, потому что не нашел в <stdexcept> и в <exception> out_of_bounds. Его наверное нужно самому определять?

Еще к этому итератору самому нужно добавить операции +,-,< и т.д.
Вот как мне это сделать? Что под операцией '+' понимается для итераторов? Это что мне нужно, если допустим один итератор указывает на второй элемент, а другой на третий, то когда я прибавлю один итератор к другому у меня должен получится третий итератор который будет указывать на пятый элемент (2+3) ??? А операция '<' это что если it1 указывает на второй элемент, а it2 на третий, то когда it1<it2 должно вернутся true?????

Добавлено через 25 минут
C++
1
d<-(curr-c->begin())
Тут строчка не сильно ясна, это что унарный минус???
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
25.07.2013, 04:13
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Checked_iter (C++):

Checked_Iter - C++
Вот такой вопрос. Нужно переделать Checked_Iter для недействительных итераторов. Как сделать их &quot;проверяемыми&quot;, чтобы это было универсально...

Checked_Iter - C++
Вот такой вопрос. Нужно переделать Checked_Iter для недействительных итераторов. Как сделать их &quot;проверяемыми&quot;, чтобы это было универсально...

Checked_Iter - C++
Вот такой вопрос. Нужно переделать Checked_Iter для недействительных итераторов. Как сделать их &quot;проверяемыми&quot;, чтобы это было универсально...

Checked_Iter - C++
Вот такой вопрос. Нужно переделать Checked_Iter для недействительных итераторов. Как сделать их &quot;проверяемыми&quot;, чтобы это было универсально...

Checked_Iter - C++
Вот такой вопрос. Нужно переделать Checked_Iter для недействительных итераторов. Как сделать их &quot;проверяемыми&quot;, чтобы это было универсально...

Checked_Iter - C++
Вот такой вопрос. Нужно переделать Checked_Iter для недействительных итераторов. Как сделать их &quot;проверяемыми&quot;, чтобы это было универсально...

Checked_Iter - C++
Вот такой вопрос. Нужно переделать Checked_Iter для недействительных итераторов. Как сделать их &quot;проверяемыми&quot;, чтобы это было универсально...

Checked_Iter - C++
Вот такой вопрос. Нужно переделать Checked_Iter для недействительных итераторов. Как сделать их &quot;проверяемыми&quot;, чтобы это было универсально...

Checked_Iter - C++
Вот такой вопрос. Нужно переделать Checked_Iter для недействительных итераторов. Как сделать их &quot;проверяемыми&quot;, чтобы это было универсально...

Checked_Iter - C++
Вот такой вопрос. Нужно переделать Checked_Iter для недействительных итераторов. Как сделать их &quot;проверяемыми&quot;, чтобы это было универсально...

Checked_Iter - C++
Вот такой вопрос. Нужно переделать Checked_Iter для недействительных итераторов. Как сделать их &quot;проверяемыми&quot;, чтобы это было универсально...

Checked_Iter - C++
Вот такой вопрос. Нужно переделать Checked_Iter для недействительных итераторов. Как сделать их &quot;проверяемыми&quot;, чтобы это было универсально...

Checked_Iter - C++
Вот такой вопрос. Нужно переделать Checked_Iter для недействительных итераторов. Как сделать их &quot;проверяемыми&quot;, чтобы это было универсально...

Checked_Iter - C++
Вот такой вопрос. Нужно переделать Checked_Iter для недействительных итераторов. Как сделать их &quot;проверяемыми&quot;, чтобы это было универсально...

Checked_Iter - C++
Вот такой вопрос. Нужно переделать Checked_Iter для недействительных итераторов. Как сделать их &quot;проверяемыми&quot;, чтобы это было универсально...

Checked_Iter - C++
Вот такой вопрос. Нужно переделать Checked_Iter для недействительных итераторов. Как сделать их &quot;проверяемыми&quot;, чтобы это было универсально...

Checked_Iter - C++
Вот такой вопрос. Нужно переделать Checked_Iter для недействительных итераторов. Как сделать их &quot;проверяемыми&quot;, чт

Checked_Iter - C++
Вот такой вопрос. Нужно переделать Checked_Iter для недействительных итераторов. Как сделать их &quot;проверяемыми&quot;, чтобы это было универсально...


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

Или воспользуйтесь поиском по форуму:
23
Croessmah
Ушел
Эксперт CЭксперт С++
13557 / 7707 / 872
Регистрация: 27.09.2012
Сообщений: 18,996
Записей в блоге: 3
Завершенные тесты: 1
25.07.2013, 06:38 #2
Цитата Сообщение от ninja2 Посмотреть сообщение
да и вообще что такое iterator_traits?
Долго посмотреть?
http://www.cplusplus.com/reference/iterator/iterator_traits/
Цитата Сообщение от ninja2 Посмотреть сообщение
От что такое difference_type?
Ответ по ссылке выше
0
ForEveR
В астрале
Эксперт С++
7983 / 4742 / 321
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
25.07.2013, 10:03 #3
C++
1
if(c->end()-curr<d||d<-(curr-c->begin()))throw out_of_bounds();
Данная строчка эквивалетна

C++
1
if (c->end() - curr < d || d < -(curr - c->begin())) throw out_of_bounds();
Полагаю, так понятнее.
0
ninja2
231 / 187 / 7
Регистрация: 26.09.2012
Сообщений: 2,018
Завершенные тесты: 1
26.07.2013, 03:44  [ТС] #4
ForEveR, Да понятно а от арифметические операции над указателями, итератор это можно сказать указатель, от есть у нас int* p. Первый элемент допустим указывает на 2000, второй на 2004, третий на 2008, от если мы отнимим от второго первый элемент(2004-2000) мы должны получить 4, а на самом деле мы ж получим 1. Так что получается оно само автоматом делит на 4. Это примерчик из какой то книги или статьи, не помню, про арифметику указателей.
Цитата Сообщение от Croessmah Посмотреть сообщение
Долго посмотреть?
Да смотрел и не раз, токо там мало что понял, токо глянул вроде понятнее стало, но все рамно зачем он используется, затем чтобы задать обобщенный тип? iterator используется для того чтобы задать какой то определенный тип итератора, а iterator_traits (черты итератора) чтобы задать как бы все итераторы?
Он походу так же используется как и unique_function, для того чтобы просто задать имена typedef с известными именами

Добавлено через 15 часов 41 минуту
ЕСть еще задание: "Переделайте Checked_iter так, чтобы проверять недействительные итераторы."
Как его сделать? Недействительные итераторы это когда мы создали этот итератор, а затем изменили resize() размер контейнера и некоторые итераторы могут стать недействительными. Как же мне это сделать? Нужно наверно в каждом методе, разыменование, инкремент, декремент перепроверять диапазон? В книге нету примера, нужно самому додумать.
Давайте попытаемся просто теоретически разобрать, без кода!!!!

Добавлено через 7 минут
От код, который не работает так как нужно.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    try
    {
        cout <<*p<<endl;
        ++p;
        //ls.resize(2);
        cout <<*p<<endl;
        ++p;
        ls.resize(2);//делает p недействительным
        cout <<*p<<endl;
        //cout <<"p-p1 = "<<(p-p1)<<endl;
 
    }
    catch(out_of_bounds)
    {
        cout <<"event be except"<<endl;
    }
 
    return 0;
0
ForEveR
В астрале
Эксперт С++
7983 / 4742 / 321
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
26.07.2013, 09:15 #5
ninja2, Ну да, просто проверить диапазон, в чем проблема?
0
Tulosba
:)
Эксперт С++
4397 / 3233 / 297
Регистрация: 19.02.2013
Сообщений: 9,045
26.07.2013, 09:50 #6
Цитата Сообщение от ninja2 Посмотреть сообщение
(2004-2000) мы должны получить 4, а на самом деле мы ж получим 1. Так что получается оно само автоматом делит на 4.
В общем случае разница считается в кол-ве элементов типа, на который указывает итератор, а не в кол-ве байт.
Цитата Сообщение от ninja2 Посмотреть сообщение
iterator_traits (черты итератора) чтобы задать как бы все итераторы?
Т.к. итераторы не обязаны наследовать от единого базового класса (а порой "итератор" и вовсе не является классом), в стандартную библиотеку введен (шаблонный) тип iterator_traits, который является хранилищем свойств того или иного итератора. Это позволяет писать алгоритмы, опираясь на iterator_traits<класс_итератора>.
1
ninja2
231 / 187 / 7
Регистрация: 26.09.2012
Сообщений: 2,018
Завершенные тесты: 1
26.07.2013, 12:23  [ТС] #7
Цитата Сообщение от ForEveR Посмотреть сообщение
Ну да, просто проверить диапазон, в чем проблема?
А как же его проверить? Пытаюсь проверить. Написал функцию valid1()
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
    void valid1()const
    {
        //if(c->end()==p)return;//если конец, то возврат
        //if(c->end()==curr)out_of_bounds();
        for(Iter pp=c->begin();pp!=c->end();++pp)
        {
// Эту стррочку когда добавляю то сразу же падает
//pp==curr;
            cout <<"(*c).size()= "<<(*c).size()<<' '<<*pp<<endl;
            if(pp==curr)
            {
                //cout <<"mu tyt "<<endl;exit(1);
                //cout <<"&pp= "<<pp<<" &p= "<<p<<endl;
                //cout <<"pp= "<<*pp<<" p= "<<*p<<endl;//exit(1);
                return;//если pp=p, то елемент найден возврат
            }
        }
        throw out_of_bounds();//элемент не находится в последовательности выход
    }
Добавляю valid1() в оператор operator*() в самом начале вызова, он проверяет текущий итератор Iter Curr входит ли он в последовательность. Послед resize() последовательности уже не возможно проверить, сразу же выбрасывается окно ошибки, падает при обращении pp==curr;

Полностью код
Кликните здесь для просмотра всего текста
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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
//Chacked_iter
#include <iostream>
using std::cout;
using std::endl;
using std::cerr;
#include <list>
using std::list;
#include <string>
using std::string;
#include <vector>
using std::vector;
#include <iterator>
using std::iterator_traits;
using std::advance;
#include <cstdlib>
using std::exit;
 
struct out_of_bounds{};
 
template<class Cont,class Iter=typename Cont::iterator>
class Checked_iter : public iterator_traits<Iter>//наследует все типы итераторов
{
public:
    Iter curr;//итератор для текущей позиции
    Cont* c;//указатель на текущий элемент
    //...
 
    //проверка на валидность переданного итератора
    void valid(Iter p)const
    {
        if(c->end()==p)return;//если конец, то возврат
        for(Iter pp=c->begin();pp!=c->end();++pp) if(pp==p)return;//если pp=p, то елемент найден возврат
        throw out_of_bounds();//элемент не находится в последовательности выход
    }
 
    void valid1()const
    {
        //if(c->end()==p)return;//если конец, то возврат
        //if(c->end()==curr)out_of_bounds();
        for(Iter pp=c->begin();pp!=c->end();++pp)
        {
            //pp==curr; Эту стррочку когда добавляю то сразу же падает
            cout <<"(*c).size()= "<<(*c).size()<<' '<<*pp<<endl;
            if(pp==curr)
            {
                //cout <<"mu tyt "<<endl;exit(1);
                //cout <<"&pp= "<<pp<<" &p= "<<p<<endl;
                //cout <<"pp= "<<*pp<<" p= "<<*p<<endl;//exit(1);
                return;//если pp=p, то елемент найден возврат
            }
        }
        throw out_of_bounds();//элемент не находится в последовательности выход
    }
 
    //оператор сравнения
    friend bool operator==(const Checked_iter& i,const Checked_iter& j)
    {
        return i.c==j.c&&i.curr==j.curr;
    }
 
    //нет умолчательного инициализатора (конструктора по умолчанию)
    //конструктор предобразования
    Checked_iter(Cont& x, Iter p) :c(&x),curr(p){valid(p);}
    //конструктор копирования
    Checked_iter(Cont& x) :c(&x),curr(x.begin()){}
 
    //операция разыменования
    reference operator*()const
    {
        valid1();
        cout <<"dal6we"<<endl;
        if(curr==c->end())throw out_of_bounds();//еси текущий элемент равен консу, то генерация выхода за границы
        return *curr;//если не равен, то возврат значения по ссылке
    }
 
    //доступ через указатель
    pointer operator->() const
    {
        if(curr==c->end())throw out_of_bounds();//если текущий элемент равен концу, то генерация выхода за границы
        return &*curr;//возврат указателя на элемент
    }
 
    //операция '+'
    Checked_iter operator+(difference_type d)const//только для итераторов произвольного доступа
    {
        //тут похоже какието действия с указателями
        //если указатель на конец минус текущий указатель меньше d
        //d похоже на число которое передается для сдвига итератора
        //c->end()-curr вернет количество элементов до последнего
        //-(curr-c->begin()) 
        if(c->end()-curr<d||d<-(curr-c->begin()))throw out_of_bounds();
        return Checked_iter(c,curr+d);
    }
 
    reference operator[](difference_type d)const//только для итераторов произвольного доступа
    {
        if(c->end()-curr<=d||d<-(curr-c->begin()))throw out_of_bounds();
        return curr[d];
    }
 
    Checked_iter operator++ ()//префиксный ++
    {
        if(curr==c->end())throw out_of_bounds();
        ++curr;
        return *this;
    }
 
    Checked_iter operator++(int)//постфиксный ++
    {
        Checked_iter tmp=*this;
        ++*this;//проверяется префиксным ++
        return tmp;
    }
 
    Checked_iter operator--()//префиксный
    {
        if(curr==c->begin())throw out_of_bounds();
        --curr;
        return *this;
    }
 
    Checked_iter operator--(int)//постфиксный --
    {
        Checked_iter tmp=*this;
        --*this;//проверяется префиксным --
        return tmp;
    }
 
    difference_type index()const {return curr-c->begin();}//только произвольный доступ
    //Видимо без проверки возврат текущего итератора
    //просто типа итератора возврат
    Iter unchecked() const {return curr;}
    //+,-,< и т.д.(параграф 19.6[6])
    difference_type operator-(const Checked_iter& x)
    {
        valid(x);
        return (curr-y);
    }
};
 
int main()
{
    cout <<"Chacked_iter"<<endl;
    vector<string> ls;
    ls.push_back("hellow");
    ls.push_back("world");
    ls.push_back("gacpada");
    ls.push_back("da");
    ls.push_back("net");
    vector<string>::iterator it,it1;
    it=ls.begin();
    advance(it,3);
    //if(c->end()-curr<d||d<-(curr-c->begin()))throw out_of_bounds();
    if(ls.end()-it<2||2<-(it-ls.begin()))cout <<"don't work"<<endl;
    cout <<"*it= "<<*it<<' '<<(ls.end()-it)<<endl;
    cout <<"*it= "<<*it<<' '<<-(it-ls.begin())<<endl;
    
 
    Checked_iter<vector<string> > p(ls,ls.begin());
    Checked_iter<vector<string> > p1(ls,ls.begin());
    try
    {
        cout <<*p<<endl;
        ++p;
        //ls.resize(2);
        cout <<*p<<endl;
        ++p;
        ls.resize(2);
        cout <<"ls.size()= "<<ls.size()<<endl;
        
    //  --p;
        cout <<*p<<endl;
        //cout <<"p-p1 = "<<(p-p1)<<endl;
 
    }
    catch(out_of_bounds)
    {
        cout <<"event be except"<<endl;
    }
 
    return 0;
}


Добавлено через 20 минут
При resize выделяется новая область памяти под vector и мб сам Cont* c;//указатель на текущий элемент
становится уже не действительным, хотя он не вызывает ошибки да и наверно наврятли с это просто указывает на объект в котором находятся указатели, которые resize() поменяла, поэтому скорее всего ошибки тут не должно быть, смутно все так представляется. С Cont* c все в порядке нету ошибки. Я еще проверил функцией чтобы наверняка:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void valid1()const
    {
        //if(c->end()==p)return;//если конец, то возврат
        //if(c->end()==curr)out_of_bounds();
        for(Iter pp=c->begin();pp!=c->end();++pp)
        {
            //pp==curr; Эту стррочку когда добавляю то сразу же падает
            cout <<"(*c).size()= "<<(*c).size()<<' '<<*pp<<endl;
            /*if(pp==curr)
            {
                //cout <<"mu tyt "<<endl;exit(1);
                //cout <<"&pp= "<<pp<<" &p= "<<p<<endl;
                //cout <<"pp= "<<*pp<<" p= "<<*p<<endl;//exit(1);
                return;//если pp=p, то елемент найден возврат
            }*/
        }
        return;
        throw out_of_bounds();//элемент не находится в последовательности выход
    }
ошибки нету c выводится нормально

Тогда остается Iter curr. Указывает на какой то адрес. После resize() что происходит с этим указателем?
В примере он указывает на третий элемент. Происходит resize() элементы перекопировались в новую область памяти, а curr остался указывать на старую область памяти, которая уж не находится в последовательности. И почему же тогда при pp==curr возникает ошибка, если curr хранит в себе просто недействительный адрес?

Добавлено через 5 минут
Да и от когда я делаю resize(2) то тогда только указатель недействительный, а если я делаю resize(3), то у меня почему то указатель действительный. Почему? Должен же стать недействительный ведь новая область памяти выделена, а указатель указывает на старую. От я даже уже и для resize(4) попробовал то же самое происходит никакой новой памяти не выделяется, если б выделялась, то указатели становились бы недействительные???
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
    try
    {
        cout <<*p<<endl;
        ++p;
        //ls.resize(2);
        cout <<*p<<endl;
        ++p;
        ls.resize(4);
        cout <<"ls.size()= "<<ls.size()<<endl;
        
    //  --p;
        cout <<*p<<endl;
        //cout <<"p-p1 = "<<(p-p1)<<endl;
 
    }
    catch(out_of_bounds)
    {
        cout <<"event be except"<<endl;
    }
Добавлено через 7 минут
И вообще когда я пытаюсь посмотреть адрес на который указывают итераторы у меня не получается их вывести. Я делаю так cout <<curr<<' '<<pp<<endl;

ошибка: "c:\test\test\test\main.cpp(42): error C2679: бинарный "<<": не найден оператор, принимающий правый операнд типа "const std::_Vector_iterator<_Myvec>" (или приемлемое преобразование отсутствует)"
0
ForEveR
В астрале
Эксперт С++
7983 / 4742 / 321
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
26.07.2013, 13:15 #8
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
#include <vector>
#include <iostream>
#include <exception>
#include <stdexcept>
 
template<typename Container, typename Iterator = typename Container::iterator>
class checked_iterator
{
public:
   checked_iterator(Container& cnt, Iterator pos) :
      container_(&cnt), position_(pos)
   {
   }
   checked_iterator(const checked_iterator& rhs) :
      container_(&rhs.container_), position_(rhs.position_)
   {
   }
   checked_iterator& operator ++()
   {
      check_valid();
      ++position_;
      return *this;
   }
   checked_iterator operator ++ (int)
   {
      checked_iterator tmp(*this);
      this->operator ++();
      return tmp;
   }
   typename Container::const_reference operator * () const
   {
      return const_cast<typename Container::reference>
      (const_cast<checked_iterator&>(*this).operator *());
   }
   typename Container::reference operator * ()
   {
      check_valid();
      return *position_;
   }
   friend bool operator == (const checked_iterator& first, const checked_iterator& second)
   {
      return first.container_ == second.container_ && first.position_ == second.position_;
   }
   friend bool operator != (const checked_iterator& first, const checked_iterator& second)
   {
      return !(first == second);
   }
private:
   void check_valid() const
   {
      for (typename Container::const_iterator pos = container_->begin(); pos != container_->end(); ++pos)
      {
         if (pos == position_)
         {
            return;
         }
      }
      throw std::out_of_range("invariant failed");
   }
 
   Container* container_;
   Iterator position_;
};
 
int main()
{
   std::vector<int> vec = {1,2,3,4};
   checked_iterator<std::vector<int> > c_begin(vec, vec.begin()), c_end(vec, vec.end());
   for (; c_begin != c_end; ++c_begin)
   {
      std::cout << *c_begin << std::endl;
   }
   checked_iterator<std::vector<int> > next_c_begin(vec, vec.begin());
   vec.resize(100);
   try
   {
      for (; next_c_begin != c_end; ++next_c_begin)
      {
         std::cout << *next_c_begin << std::endl;
      }
   }
   catch (const std::exception& e)
   {
      std::cout << e.what() << std::endl;
   }
}
Bash
1
2
3
4
5
6
./new
1
2
3
4
invariant failed
Если проверка на равенство не работает - значит используется debug режим, в котором свои checked итераторы. Итераторы нельзя выводить в поток. Можно вывести либо адрес итератора, либо адрес элемента на который указывает итератор (совсем не факт, что сработает, если итератор инвалидировался). Можно сделать еще один вариант, сохранять после каждой операции размер контейнера/адрес буфера, и в check_valid просто проверять, что они до сих пор совпадают.
1
ninja2
231 / 187 / 7
Регистрация: 26.09.2012
Сообщений: 2,018
Завершенные тесты: 1
26.07.2013, 17:35  [ТС] #9
ForEveR, У меня код не запускается. Я его чуток подредактировал под visual studio 2010
Кликните здесь для просмотра всего текста
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
#include <vector>
#include <iostream>
#include <exception>
#include <stdexcept>
 
template<typename Container, typename Iterator = typename Container::iterator>
class checked_iterator
{
public:
   checked_iterator(Container& cnt, Iterator pos) :
      container_(&cnt), position_(pos)
   {
   }
   checked_iterator(const checked_iterator& rhs) :
      container_(&rhs.container_), position_(rhs.position_)
   {
   }
   checked_iterator& operator ++()
   {
      check_valid();
      ++position_;
      return *this;
   }
   checked_iterator operator ++ (int)
   {
      checked_iterator tmp(*this);
      this->operator ++();
      return tmp;
   }
   typename Container::const_reference operator * () const
   {
      return const_cast<typename Container::reference>
      (const_cast<checked_iterator&>(*this).operator *());
   }
   typename Container::reference operator * ()
   {
      check_valid();
      return *position_;
   }
   friend bool operator == (const checked_iterator& first, const checked_iterator& second)
   {
      return first.container_ == second.container_ && first.position_ == second.position_;
   }
   friend bool operator != (const checked_iterator& first, const checked_iterator& second)
   {
      return !(first == second);
   }
private:
   void check_valid() const
   {
       //std::cout <<"Mu tyt"<<std::endl;
      for (typename Container::const_iterator pos = container_->begin(); pos != container_->end(); ++pos)
      {
        //  pos==position_;
          std::cout <<"Mu tyt"<<std::endl;
          std::cout <<"*pos= "<<*pos<<' '<<"*position_= "<<*position_<<std::endl;
         if (pos == position_)
         {
            return;
         }
      }
      throw std::out_of_range("invariant failed");
   }
 
   Container* container_;
   Iterator position_;
};
 
int main()
{
    int mass[]={1,2,3,4};
   std::vector<int> vec(mass,mass+4);
   checked_iterator<std::vector<int> > c_begin(vec, vec.begin()), c_end(vec, vec.end());
   for (; c_begin != c_end; ++c_begin)
   {
      std::cout << *c_begin << std::endl;
   }
   checked_iterator<std::vector<int> > next_c_begin(vec, vec.begin());
   vec.resize(100);
   try
   {
       std::cout <<"Perexodim k cikly"<<std::endl;
       next_c_begin!=c_end;//тут сразу выбрасывается ошибка
       std::cout <<"nex_c_begin!=c_end"<<std::endl;//эта строчка не выведется
      for (; next_c_begin != c_end; ++next_c_begin)
      {
          std::cout <<"Mu eje v cikle"<<std::endl;
         std::cout << *next_c_begin << std::endl;
      }
   }
   catch (const std::exception& e)
   {
      std::cout << e.what() << std::endl;
   }
}


В этой строчке ошибка.
C++
1
next_c_begin!=c_end;//тут сразу выбрасывается ошибка
0
Миниатюры
Checked_iter  
ninja2
231 / 187 / 7
Регистрация: 26.09.2012
Сообщений: 2,018
Завершенные тесты: 1
26.07.2013, 17:39  [ТС] #10
Что это значит у меня дебаг режим работает?
0
gray_fox
What a waste!
1522 / 1227 / 70
Регистрация: 21.04.2012
Сообщений: 2,565
Завершенные тесты: 3
26.07.2013, 17:40 #11
Цитата Сообщение от ninja2 Посмотреть сообщение
Что это значит у меня дебаг режим работает?
Да.
1
ForEveR
В астрале
Эксперт С++
7983 / 4742 / 321
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
26.07.2013, 17:43 #12
ninja2, А то, что там написано DEBUG Assertion Failed ничего не говорит?
Можно просто сделать итераторы MSVC unchecked - как написано в гугле.
0
ninja2
231 / 187 / 7
Регистрация: 26.09.2012
Сообщений: 2,018
Завершенные тесты: 1
26.07.2013, 17:45  [ТС] #13
ForEveR, check_valid тоже делает что и моя valid1, обход вектора и сравнивает указатели.
0
ForEveR
В астрале
Эксперт С++
7983 / 4742 / 321
Регистрация: 24.06.2010
Сообщений: 10,547
Завершенные тесты: 3
26.07.2013, 17:46 #14
ninja2, Да, и что далее? Отключите дебаг режим/отключите checked итераторы.
1
ninja2
231 / 187 / 7
Регистрация: 26.09.2012
Сообщений: 2,018
Завершенные тесты: 1
26.07.2013, 17:47  [ТС] #15
gray_fox, А можно в визуал студио просто скомпилировать программу без дебага? Я просто контр ф5 нажимаю это с дебагом походу, а без дебага? Мб скомпилируется, а затем запустю посмотрю результат.

Добавлено через 24 секунды
ForEveR, А как его отключить я не знаю?
0
26.07.2013, 17:47
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.