Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
Nikitko_Cent
144 / 114 / 37
Регистрация: 27.10.2011
Сообщений: 690
Завершенные тесты: 3
#1

Реализация std::list<>::begin() - C++

27.09.2015, 00:05. Просмотров 801. Ответов 13
Метки нет (Все метки)

Вопрос строго для знатоков реализации STL.
Каким образом реализована "перегрузка" у списка метода begin() только по возвращаемому значению? Т.е. этот метод может возвращать как iterator, так и const_iterator
Я лично вижу тут два пути : либо const_iterator наследуется от iterator (или наоборот), либо const_iterator является другом iterator (или наоборот). Но хочется знать уж наверняка (реализую свой список-велосипед, и не знаю как лучше поступить)
P.S. пытался курить сорцы list.h, но там просто ад
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
27.09.2015, 00:05
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Реализация std::list<>::begin() (C++):

Реализация std::list, сложность list::size()
Часто приходилось пользоваться Listом, но сейчас столкнулся с небольшой...

Std::begin() ,std::end(),std::copy
...// int main() { std::vector&lt;double&gt; data;//Работает cout &lt;&lt;...

Реализация класса MyString. Стандартная библиотека, std::string, std::vector
как добавить реализацию конкатенации строк через перегрузку оператора &quot;+=&quot; в...

Какая реализация лучше? std::pointer_to_binary_function vs std::function
Какая реализация (set_p или set_f) лучше /современнее / эффективнее ?...

Потокобезопасность std::map::end, std::list::end
Собсна сабж, могу ли я без синхронизаций выполнять подобного рода код if...

Разъясните код пжлст(выдает ошибку:cannot convert from 'class std::list<class c_bullet *,class std::allocator<class c_bullet *> >::iterator' to 'int')
Есть такие строки: std::list&lt;c_bullet*&gt; Bullets; ... for(auto i =...

13
Perfilov
264 / 164 / 56
Регистрация: 25.02.2015
Сообщений: 435
27.09.2015, 00:08 #2
const_terator begin() const;
iterator begin();

т.е. константный метод возвращает константный итератор, и неконстантный - неконстантный
какой из них звать - компилятор определяет из контекста вызова метода.
0
Nikitko_Cent
144 / 114 / 37
Регистрация: 27.10.2011
Сообщений: 690
Завершенные тесты: 3
27.09.2015, 00:09  [ТС] #3
Цитата Сообщение от Perfilov Посмотреть сообщение
т.е. константный метод возвращает константный итератор, и неконстантный - неконстантный
какой из них звать - компилятор определяет из контекста вызова метода.
Не определяет.
По стандарту, методы не могут быть перегружены только по возвращаемому значению - сигнатура полностью совпадает
0
Perfilov
264 / 164 / 56
Регистрация: 25.02.2015
Сообщений: 435
27.09.2015, 00:12 #4
константность\неконстантность метода в сигнатуру входит. или как тогда по вашему разруливается то, о чем пишет ТС?
0
Nikitko_Cent
144 / 114 / 37
Регистрация: 27.10.2011
Сообщений: 690
Завершенные тесты: 3
27.09.2015, 00:19  [ТС] #5
Цитата Сообщение от Perfilov Посмотреть сообщение
константность\неконстантность метода в сигнатуру входит. или как тогда по вашему разруливается то, о чем пишет ТС?
Хм, тогда я чего-то не понимаю.
Вот код :
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
template<typename T>
class Linked_list
{
public:
    class Iterator
    {
    public:
        Iterator();
        Iterator(const Iterator &iterator);
 
        Iterator& operator=(const Iterator &right);
        bool operator!=(const Iterator &right) const;
        bool operator==(const Iterator &right) const;
 
        T& operator*() const;   
        T* operator->() const;
 
        Iterator& operator++();
        Iterator operator++(int);
        Iterator& operator--();
        Iterator operator--(int);
    };
 
    class Const_Iterator
    {
    public:
        Const_Iterator();
        Const_Iterator(const Const_Iterator &iterator);
 
        Const_Iterator& operator=(const Const_Iterator &right);
        bool operator!=(const Const_Iterator &right) const;
        bool operator==(const Const_Iterator &right) const;
 
        const T& operator*() const;
        const T* operator->() const;
 
        Const_Iterator& operator++();
        Const_Iterator operator++(int);
        Const_Iterator& operator--();
        Const_Iterator operator--(int);
    };
 
    Iterator begin();   
    Iterator end();     
    
    Const_Iterator begin() const;
    Const_Iterator end() const;
};
Вот использование:
C++
1
2
3
Linked_list<int> list;
...
for (Linked_list<int>::Const_Iterator iter = list.begin(); iter != list.end(); iter++)
Ну и результат:
Ошибка 1 error C2440: инициализация: невозможно преобразовать "Linked_list<int>::Iterator" в "Linked_list<int>::Const_Iterator"
Ошибка 2 error C2679: бинарный "!=": не найден оператор, принимающий правый операнд типа "Linked_list<int>::Iterator" (или приемлемое преобразование отсутствует)
Т.е. компилятор хочет, чтобы я ему предоставил конструктор "преобразования"
0
Perfilov
264 / 164 / 56
Регистрация: 25.02.2015
Сообщений: 435
27.09.2015, 00:28 #6
ну да. это вроде логично. например неконстантный инт может к константному преобразоваться неявно. логично это ожидать и от итератора. явно кастить неконстантный в константный - это ахтунг а не код будет. а вот как это сделано - я не скажу, не знаю. либо наследованием, либо у константного есть конструктор или еще как-то. нет литературы под рукой глянуть и компа нормального тоже.

Добавлено через 3 минуты
еще что-то слышал про методы std::cbegin std::cend, которые должны в вашем случае решить проблему преобразования. ибо они будут возвращать константные итераторы. но хз стандартные ли они или нет. std::begin std::end - точно в стандарте
0
DrOffset
7518 / 4514 / 1097
Регистрация: 30.01.2014
Сообщений: 7,362
27.09.2015, 00:36 #7
Nikitko_Cent, собственно, можно ведь просто посмотреть как это реализовано в стандартной библиотеке.
Например в реализации std:: в gcc используется конструктор преобразования nonconst -> const
C++
1
2
3
4
5
6
      typedef _List_iterator<_Tp>                iterator;
     
      //.................
 
      _List_const_iterator(const iterator& __x) _GLIBCXX_NOEXCEPT
      : _M_node(__x._M_node) { }
1
Nikitko_Cent
144 / 114 / 37
Регистрация: 27.10.2011
Сообщений: 690
Завершенные тесты: 3
27.09.2015, 00:39  [ТС] #8
DrOffset, так вот, я к тому, каким образом реализован доступ к приватному (я надеюсь ) полю объекта __x из другого класса:
Цитата Сообщение от Nikitko_Cent Посмотреть сообщение
Я лично вижу тут два пути : либо const_iterator наследуется от iterator (или наоборот), либо const_iterator является другом iterator (или наоборот). Но хочется знать уж наверняка (реализую свой список-велосипед, и не знаю как лучше поступить)
0
DrOffset
7518 / 4514 / 1097
Регистрация: 30.01.2014
Сообщений: 7,362
27.09.2015, 00:44 #9
Цитата Сообщение от Nikitko_Cent Посмотреть сообщение
так вот, я к тому, каким образом реализован доступ к приватному (я надеюсь ) полю объекта x из другого класса:
Они не приватные. Это структура.
Ну если очень хочется засунуть в приват, то можно использовать friend class Iterator; для const версии.

Добавлено через 2 минуты
Цитата Сообщение от Nikitko_Cent Посмотреть сообщение
P.S. пытался курить сорцы list.h, но там просто ад
Кстати, не знаю уж чего там адового. Нормальный код.
Кликните здесь для просмотра всего текста
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
  template<typename _Tp>
    struct _List_iterator
    {
      typedef _List_iterator<_Tp>                _Self;
      typedef _List_node<_Tp>                    _Node;
 
      typedef ptrdiff_t                          difference_type;
      typedef std::bidirectional_iterator_tag    iterator_category;
      typedef _Tp                                value_type;
      typedef _Tp*                               pointer;
      typedef _Tp&                               reference;
 
      _List_iterator() _GLIBCXX_NOEXCEPT
      : _M_node() { }
 
      explicit
      _List_iterator(__detail::_List_node_base* __x) _GLIBCXX_NOEXCEPT
      : _M_node(__x) { }
 
      _Self
      _M_const_cast() const _GLIBCXX_NOEXCEPT
      { return *this; }
 
      // Must downcast from _List_node_base to _List_node to get to _M_data.
      reference
      operator*() const _GLIBCXX_NOEXCEPT
      { return static_cast<_Node*>(_M_node)->_M_data; }
 
      pointer
      operator->() const _GLIBCXX_NOEXCEPT
      { return std::__addressof(static_cast<_Node*>(_M_node)->_M_data); }
 
      _Self&
      operator++() _GLIBCXX_NOEXCEPT
      {
    _M_node = _M_node->_M_next;
    return *this;
      }
 
      _Self
      operator++(int) _GLIBCXX_NOEXCEPT
      {
    _Self __tmp = *this;
    _M_node = _M_node->_M_next;
    return __tmp;
      }
 
      _Self&
      operator--() _GLIBCXX_NOEXCEPT
      {
    _M_node = _M_node->_M_prev;
    return *this;
      }
 
      _Self
      operator--(int) _GLIBCXX_NOEXCEPT
      {
    _Self __tmp = *this;
    _M_node = _M_node->_M_prev;
    return __tmp;
      }
 
      bool
      operator==(const _Self& __x) const _GLIBCXX_NOEXCEPT
      { return _M_node == __x._M_node; }
 
      bool
      operator!=(const _Self& __x) const _GLIBCXX_NOEXCEPT
      { return _M_node != __x._M_node; }
 
      // The only member points to the %list element.
      __detail::_List_node_base* _M_node;
    };
 
  /**
   *  @brief A list::const_iterator.
   *
   *  All the functions are op overloads.
  */
  template<typename _Tp>
    struct _List_const_iterator
    {
      typedef _List_const_iterator<_Tp>          _Self;
      typedef const _List_node<_Tp>              _Node;
      typedef _List_iterator<_Tp>                iterator;
 
      typedef ptrdiff_t                          difference_type;
      typedef std::bidirectional_iterator_tag    iterator_category;
      typedef _Tp                                value_type;
      typedef const _Tp*                         pointer;
      typedef const _Tp&                         reference;
 
      _List_const_iterator() _GLIBCXX_NOEXCEPT
      : _M_node() { }
 
      explicit
      _List_const_iterator(const __detail::_List_node_base* __x)
      _GLIBCXX_NOEXCEPT
      : _M_node(__x) { }
 
      _List_const_iterator(const iterator& __x) _GLIBCXX_NOEXCEPT
      : _M_node(__x._M_node) { }
 
      iterator
      _M_const_cast() const _GLIBCXX_NOEXCEPT
      { return iterator(const_cast<__detail::_List_node_base*>(_M_node)); }
 
      // Must downcast from List_node_base to _List_node to get to
      // _M_data.
      reference
      operator*() const _GLIBCXX_NOEXCEPT
      { return static_cast<_Node*>(_M_node)->_M_data; }
 
      pointer
      operator->() const _GLIBCXX_NOEXCEPT
      { return std::__addressof(static_cast<_Node*>(_M_node)->_M_data); }
 
      _Self&
      operator++() _GLIBCXX_NOEXCEPT
      {
    _M_node = _M_node->_M_next;
    return *this;
      }
 
      _Self
      operator++(int) _GLIBCXX_NOEXCEPT
      {
    _Self __tmp = *this;
    _M_node = _M_node->_M_next;
    return __tmp;
      }
 
      _Self&
      operator--() _GLIBCXX_NOEXCEPT
      {
    _M_node = _M_node->_M_prev;
    return *this;
      }
 
      _Self
      operator--(int) _GLIBCXX_NOEXCEPT
      {
    _Self __tmp = *this;
    _M_node = _M_node->_M_prev;
    return __tmp;
      }
 
      bool
      operator==(const _Self& __x) const _GLIBCXX_NOEXCEPT
      { return _M_node == __x._M_node; }
 
      bool
      operator!=(const _Self& __x) const _GLIBCXX_NOEXCEPT
      { return _M_node != __x._M_node; }
 
      // The only member points to the %list element.
      const __detail::_List_node_base* _M_node;
    };
0
Nikitko_Cent
144 / 114 / 37
Регистрация: 27.10.2011
Сообщений: 690
Завершенные тесты: 3
27.09.2015, 00:45  [ТС] #10
Цитата Сообщение от DrOffset Посмотреть сообщение
Они не приватные. Это структура.
Это я чтоли смогу из любого куска кода написать iter._M_node = ... ? (относительно gcc)
Интересная картина...
0
Perfilov
264 / 164 / 56
Регистрация: 25.02.2015
Сообщений: 435
27.09.2015, 00:48 #11
у итераторов может быть общий предок, в котором этиданные - протектед. итого, откуда угодно не будет доступа. да и другими способами можно это порешать. вот до студии добрался. там преобразования за счет наследования работают:

C++
1
2
3
template<class _Mylist>
    class _List_iterator
        : public _List_const_iterator<_Mylist>
0
DrOffset
7518 / 4514 / 1097
Регистрация: 30.01.2014
Сообщений: 7,362
27.09.2015, 00:48 #12
Цитата Сообщение от Nikitko_Cent Посмотреть сообщение
Это я чтоли смогу из любого куска кода написать iter._M_node = ... ? (относительно gcc)
Ну и что. Если это не документировано, считай этого нет.
Взять, допустим, структуру FILE из С. Вот ты много ли знаешь о ее содержимом? Между тем, оно точно так же открыто всем на обозрение. Конечно, контракт, контролируемый на этапе компиляции - это хорошо, но это не обязательное требование.
0
Nikitko_Cent
144 / 114 / 37
Регистрация: 27.10.2011
Сообщений: 690
Завершенные тесты: 3
27.09.2015, 00:54  [ТС] #13
Цитата Сообщение от DrOffset Посмотреть сообщение
Кстати, не знаю уж чего там адового. Нормальный код.
Я пишу в VC++, там как то всё сложнее реализовано. Я тупо не могу найти код реализации константного итератора
0
Renji
2142 / 1501 / 456
Регистрация: 05.06.2014
Сообщений: 4,339
27.09.2015, 01:00 #14
Цитата Сообщение от Nikitko_Cent Посмотреть сообщение
DrOffset, так вот, я к тому, каким образом реализован доступ к приватному (я надеюсь ) полю объекта __x из другого класса
Ну, мне нравится такой подход:
C++
1
2
3
4
5
6
7
8
template<bool is_const_iterator>
class my_iterator
{
public:
    my_iterator(const my_iterator<false>&src):data(src.data){}
private:
    std::conditional<is_const_iterator,const int*,int*>::type data;
};
0
27.09.2015, 01:00
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
27.09.2015, 01:00
Привет! Вот еще темы с решениями:

Вопрос по std::list
Не произойдёт ли здесь какая-нибудь ошибка после удаления элемента из списка? ...

Static std::list
Добрый день, помогите решить проблему. &quot;Каждое статическое поле должно быть...

Сортировка std::list
Есть такой фрагмент програми. Создаю функцию для сортировки list. Вроде все...

Вопросы по std::list
1. Как обменять в списке два его элемента? Желательно большое быстродействие :)...


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

Или воспользуйтесь поиском по форуму:
14
Ответ Создать тему
Опции темы

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