Форум программистов, компьютерный форум, киберфорум
C++
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.92/25: Рейтинг темы: голосов - 25, средняя оценка - 4.92
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712

Изменить std::map

08.12.2019, 15:06. Показов 5320. Ответов 42
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Приветствую всех. Мне на работе приходится работать не совсем со свежим компилятором С++ и такой же старенькой библиотекой STL (там даже auto_ptr не deprecated). Обновить все это хозяйство не возможно, поэтому приходится работать с тем, что есть.
Я храню в std::map объекты своего класса. Так вот столкнулся с такой неприятной вещью, что при использовании оператора [] даже для существующего элемента вызывается конструктор по умолчанию. Сделав элементарный пример и проверив его на нескольких онлайн компиляторах я убедился, что такое поведение характерно только для моей STL.
Открыв код std::map было обнаружено, что оператор [] это, по сути, обертка над методом insert. То есть, там не происходит проверки существует ли элемент, как, например, в библиотеке STL C++Builder.
Поэтому такой вопрос. Могу ли я скопировать код файла map в файл, например my_map, добавить проверку в оператор [] и использовать этот свой файл для работы с std::map? Не возникнет ли в будущем каких-то неприятностей?
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
08.12.2019, 15:06
Ответы с готовыми решениями:

Не могу разобраться как обновить в std::map<std::string, вектор_структур>
Не могу разобраться как обновить вектор структур после его добавления в map без удаления и перезаписи struct pStruct { int...

переписать std::map
Добрый вечер! Есть работающая программа, в которой используется map, все работало хорошо, но теперь немного изменились условия и объем...

Вопрос по std::map
В качестве хэш-таблицы для строк (AnsiString) я использовал std::map. От таблицы мне нужно было ещё и такое свойство: я хотел иметь...

42
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
10.12.2019, 10:12  [ТС]
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от IGPIGP Посмотреть сообщение
автоматическая вставка объекта в мапу по оператору индексирования - известная фича.
IGPIGP, а я с этим и не спорю и не имею претензий к этому. Обратите внимание на что у меня претензии:
Цитата Сообщение от d7d1cd Посмотреть сообщение
при использовании оператора [] даже для существующего элемента вызывается конструктор по умолчанию
Поясню. У меня в мапе хранятся объекты моего класса. Если я хочу получить доступ к объекту в мапе по существующему в нем индексу, то перед получением этого доступа вызывается конструктор по умолчанию моего класса, затем деструктор. То есть, во время доступа создается и удаляется объект моего класса (ранее я написал почему так происходит):
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <map>
 
class TMyClass {
  ...
  public:
  void SomeFun();
  ...
};
 
int main() {
  std::map<int, TMyClass> m;
 
  /* Здесь конструктор вызывается и это логично - объект создается */
  m.insert(make_pair(1, TMyClass()));
 
  /* Здесь создается объект класса TMyClass, удаляется и только потом выполняется функция */
  m[1].SomeFun(); 
}
Ни в одном онлайн компиляторе такое поведение не наблюдается, что и логично: зачем создавать объект, если он уже существует в мапе? Очевидно, что сначала необходимо проверить, есть ли он там. Что я и сделал, переопределив оператор [].

Добавлено через 2 минуты
Цитата Сообщение от notAll Посмотреть сообщение
Это явно плохое решение в плане будущего саппорта кода.
То есть, сделать поведение оператора [] в мапе таким же как в подавляющем большинстве реализациях STL - плохое решение?
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
10.12.2019, 11:30
Цитата Сообщение от d7d1cd Посмотреть сообщение
Обратите внимание на что у меня претензии:
d7d1cd, я понял на что. То что я написал не о претензиях. Перечитайте. Но вы упрямы. Я же попросил вас:
Цитата Сообщение от IGPIGP Посмотреть сообщение
Покажите как вы используете этот оператор. Скорее всего проблема в том, что он вам не нужен там, где создаётся проблема.
И вы приводите полстраницы для иллюстрации своей мысли, но обесцениваете моё время. Почему бы не привести пару строк где оператор работает у вас и запускает конструктор?
Я покажу как можно привести пример. Смотрите:
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
#include <iostream>
#include <string>
#include <map>
using namespace std;
struct Bar
{
    string str;
    Bar():str("mama"){cout<<"Bar()";}
    Bar(const Bar &):str("papa"){cout<<"Bar(const Bar &)";}
};
int main()
{
map<int,string> numberedStrings;
numberedStrings[0]="mama\n";
cout<<numberedStrings.begin()->second;//mama
numberedStrings[0]="papa\n";
cout<<numberedStrings.begin()->second;//papa
 
map<int,Bar> bars;
 
Bar a ;//ctor
cout<<"\nleft value\n";
bars[0]= a ;//ctor
cout<<"\nright value\n";
cout<<bars[0].str<<endl;//no ctor called
return 0;
}
тут показано, что данный оператор не просто добавляет новую пару. он заменяет старую и тут работает конструктор. Но если я пытаюсь распечатать значение по индексу, то для возврата по значению мапа не создаст копию. Разве-что библиотеку писали идеоматически неправильные мыслители.
Вот об этом я хотел услышать.
0
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
10.12.2019, 12:01  [ТС]
Цитата Сообщение от IGPIGP Посмотреть сообщение
И вы приводите полстраницы для иллюстрации своей мысли, но обесцениваете моё время.
Прошу прощения

Цитата Сообщение от IGPIGP Посмотреть сообщение
Почему бы не привести пару строк где оператор работает у вас и запускает конструктор?
В принципе пример был в предыдущем приведенном мной коде.

Ну да ладно. Беру Ваш пример (чуть изменил, добавив cout-ов) и запускаю у себя (на своем компиляторе и "той самой" STL). Привожу результат работы кода онлайн компилятора и моего.

Запускаемый код:
Кликните здесь для просмотра всего текста
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
#include <iostream>
#include <string>
#include <map>
using namespace std;
struct Bar
{
  string str;
  Bar() : str("mama") { cout << "Bar()" << endl; }
  Bar(const Bar&) : str("papa") { cout << "Bar(const Bar &)" << cout; }
};
 
int main()
{
  map<int,string> numberedStrings;
  numberedStrings[0]="mama\n";
  cout<<numberedStrings.begin()->second;
  numberedStrings[0]="papa\n";
  cout<<numberedStrings.begin()->second;
 
  map<int,Bar> bars;
 
  Bar a;
  cout<<"\nleft value\n";
  bars[0]= a;
  cout<<"\nright value\n";
  cout<<bars[0].str<<endl;
  return 0;
}


Онлайн компилятор:
Кликните здесь для просмотра всего текста
mama
papa
Bar()

left value
Bar()

right value
mama


Мой компилятор:
Кликните здесь для просмотра всего текста
mama
papa
Bar()

left value
Bar()
Bar(const Bar &)
Bar(const Bar &)

right value
Bar()
Bar(const Bar &)
mama
0
10.12.2019, 13:15

Не по теме:

d7d1cd, это у вас там случайно не VS 6?

0
10.12.2019, 13:18  [ТС]

Не по теме:

DrOffset, нет. Операционная система IBM i. Если интересно, ниже содержимое файла map. Копирайт 1998 года :D.

Кликните здесь для просмотра всего текста
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
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
                    ??=ifndef _MAP_
                      ??=if defined(__MVS__)
                        ??=if defined(__COMPILER_VER__)
                          ??=pragma filetag("IBM-1047")
                        #endif /* defined(__COMPILER_VER__) */
                        #pragma nomargins nosequence
                        #pragma checkout(suspend)
                      #endif /* defined(__MVS__) */
                      #define _MAP_
 
// map standard header
 
#pragma info(none)
#ifndef __CHKHDR__
#  pragma report(level, E)
#endif
#pragma info(restore)
 
#if defined(__MVS__)
#  if (__IBMCPP__ < 41020)
#    error\
     This file to be used only with IBM z/OS C++ V1R2 and later compilers
#  endif /* __IBMCPP__ < 41020 */
#else
#  if (__IBMCPP__ < 400)
#    error\
     This file to be used only with IBM VisualAge C++ v4 and later compilers
#  endif /* __IBMCPP__ < 400 */
#endif /* defined(__MVS__) */
 
#if (__OS400_TGTVRM__ >= 510)
#if defined(__LLP64_IFC__) || defined(__LLP64_RTBND__)
   #pragma datamodel(LLP64)
#else
   #pragma datamodel(P128)
#endif
#endif
 
#if !(defined(__MVS__) && defined(_LP64))
#pragma object_model(compat)
#endif
#if (__OS400_TGTVRM__ > 610)
#if __V8_NAME_MANGLING
  #pragma namemangling(v8)
#else
  #pragma namemangling(v7)
#endif
#else
#pragma namemangling(ansi)
#endif
 
/**********************************************************************/
/*  <map> header file                                                 */
/*                                                                    */
/**********************************************************************/
/*                                                                    */
/*   Licensed Materials - Property of IBM.                            */
/*                                                                    */
/*   Product(s):                                                      */
/*     5722-SS1                                                       */
/*     5761-SS1                                                       */
/*     5770-SS1                                                       */
/*                                                                    */
/*   (C)Copyright IBM Corp.  1991, 2013                               */
/*                                                                    */
/*   All Rights Reserved.                                             */
/*   US Government Users Restricted Rights -                          */
/*   Use, duplication or disclosure restricted by                     */
/*   GSA ADP Schedule Contract with IBM Corp.                         */
/*                                                                    */
/**********************************************************************/
/*                                                                    */
/*  Dinkum C++ Library                                                */
/*  Copyright (c) 1998.  Licensed to IBM Corp. and its suppliers.     */
/*                                                                    */
/**********************************************************************/
 
#include <xtree>
_STD_BEGIN
                // TEMPLATE CLASS _Tmap_traits
template<class _K, class _Ty, class _Pr, class _Ax, bool _Mfl>
        class _Tmap_traits {
public:
        typedef _K key_type;
        typedef pair<const _K, _Ty> value_type;
        typedef _Pr key_compare;
        typedef typename _Ax::template rebind<value_type>::other
                allocator_type;
        enum {_Multi = _Mfl};
        _Tmap_traits()
                : comp()
                {}
        _Tmap_traits(_Pr _Parg)
                : comp(_Parg)
                {}
        class value_compare
                : public binary_function<value_type, value_type, bool> {
                friend class _Tmap_traits<_K, _Ty, _Pr, _Ax, _Mfl>;
        public:
                bool operator()(const value_type& _X,
                        const value_type& _Y) const
                        {return (comp(_X.first, _Y.first)); }
                value_compare(key_compare _Pred)
                        : comp(_Pred) {}
        protected:
                key_compare comp;
                };
        struct _Kfn {
                const _K& operator()(const value_type& _X) const
                        {return (_X.first); }
                };
        _Pr comp;
        };
 
                // TEMPLATE CLASS map
template<class _K, class _Ty,
        class _Pr _TDEF(less<_K>),
        class _A _TDEF2(allocator<pair<const _K, _Ty> >) >
        class map
                : public _Tree<_Tmap_traits<_K, _Ty, _Pr, _A, false> > {
public:
        typedef map<_K, _Ty, _Pr, _A> _Myt;
        typedef _Tree<_Tmap_traits<_K, _Ty, _Pr, _A, false> >
                _Mybase;
        typedef _K key_type;
        typedef _Ty mapped_type;
        typedef _Ty referent_type;
        typedef _Pr key_compare;
        typedef typename _Mybase::value_compare value_compare;
        typedef typename _Mybase::allocator_type allocator_type;
        typedef typename _Mybase::size_type size_type;
        typedef typename _Mybase::difference_type difference_type;
        typedef typename _Mybase::pointer pointer;
        typedef typename _Mybase::const_pointer const_pointer;
        typedef typename _Mybase::reference reference;
        typedef typename _Mybase::const_reference const_reference;
        typedef typename _Mybase::iterator iterator;
        typedef typename _Mybase::const_iterator const_iterator;
        typedef typename _Mybase::reverse_iterator reverse_iterator;
        typedef typename _Mybase::const_reverse_iterator
                const_reverse_iterator;
        typedef typename _Mybase::value_type value_type;
        map()
                : _Mybase(key_compare(), allocator_type()) {}
        explicit map(const key_compare& _Pred)
                : _Mybase(_Pred, allocator_type()) {}
        map(const key_compare& _Pred, const allocator_type& _Al)
                : _Mybase(_Pred, _Al) {}
        template<class _It>
                map(_It _F, _It _L)
                : _Mybase(key_compare(), allocator_type())
                {for (; _F != _L; ++_F)
                        _Mybase::insert(*_F); }
        template<class _It>
                map(_It _F, _It _L, const key_compare& _Pred)
                : _Mybase(_Pred, allocator_type())
                {for (; _F != _L; ++_F)
                        _Mybase::insert(*_F); }
        template<class _It>
                map(_It _F, _It _L, const key_compare& _Pred,
                const allocator_type& _Al)
                : _Mybase(_Pred, _Al)
                {for (; _F != _L; ++_F)
                        _Mybase::insert(*_F); }
        mapped_type& operator[](const key_type& _Kv)
                {iterator _P =
                        _Mybase::insert(value_type(_Kv, mapped_type())).first;
                return ((*_P).second); }
        };
 
                // TEMPLATE CLASS multimap
template<class _K, class _Ty,
        class _Pr _TDEF(less<_K>),
        class _A _TDEF2(allocator<pair<const _K, _Ty> >) >
        class multimap
                : public _Tree<_Tmap_traits<_K, _Ty, _Pr, _A, true> > {
public:
        typedef multimap<_K, _Ty, _Pr, _A> _Myt;
        typedef _Tree<_Tmap_traits<_K, _Ty, _Pr, _A, true> >
                _Mybase;
        typedef _K key_type;
        typedef _Ty mapped_type;
        typedef _Ty referent_type;      // old name, magically gone
        typedef _Pr key_compare;
        typedef typename _Mybase::value_compare value_compare;
        typedef typename _Mybase::allocator_type allocator_type;
        typedef typename _Mybase::size_type size_type;
        typedef typename _Mybase::difference_type difference_type;
        typedef typename _Mybase::pointer pointer;
        typedef typename _Mybase::const_pointer const_pointer;
        typedef typename _Mybase::reference reference;
        typedef typename _Mybase::const_reference const_reference;
        typedef typename _Mybase::iterator iterator;
        typedef typename _Mybase::const_iterator const_iterator;
        typedef typename _Mybase::reverse_iterator reverse_iterator;
        typedef typename _Mybase::const_reverse_iterator
                const_reverse_iterator;
        typedef typename _Mybase::value_type value_type;
        multimap()
                : _Mybase(key_compare(), allocator_type()) {}
        explicit multimap(const key_compare& _Pred)
                : _Mybase(_Pred, allocator_type()) {}
        multimap(const key_compare& _Pred, const allocator_type& _Al)
                : _Mybase(_Pred, _Al) {}
        template<class _It>
                multimap(_It _F, _It _L)
                : _Mybase(key_compare(), allocator_type())
                {for (; _F != _L; ++_F)
                        insert(*_F); }
        template<class _It>
                multimap(_It _F, _It _L, const key_compare& _Pred)
                : _Mybase(_Pred, allocator_type())
                {for (; _F != _L; ++_F)
                        insert(*_F); }
        template<class _It>
                multimap(_It _F, _It _L, const key_compare& _Pred,
                const allocator_type& _Al)
                : _Mybase(_Pred, _Al)
                {for (; _F != _L; ++_F)
                        insert(*_F); }
        iterator insert(const value_type& _X)
                {return (_Mybase::insert(_X).first); }
        iterator insert(iterator _P, const value_type& _X)
                {return (_Mybase::insert(_P, _X)); }
        template<class _It>
                void insert(_It _F, _It _L)
                {for (; _F != _L; ++_F)
                        insert(*_F); }
        };
_STD_END
 
#pragma namemangling(pop)
#if !(defined(__MVS__) && defined(_LP64))
#pragma object_model(pop)
#endif
 
#if (__OS400_TGTVRM__ >= 510)
   #pragma datamodel(pop)
#endif
 
#pragma info(none)
#ifndef __CHKHDR__
#  pragma report(pop)
#endif
#pragma info(restore)
 
/*
 * Copyright (c) 1998 by P.J. Plauger.  ALL RIGHTS RESERVED.
 * Consult your license regarding permissions and restrictions.
V2.3:0081 */
 
                    #if defined(__MVS__)
                      #pragma checkout(resume)
                    #endif /* defined(__MVS__) */
                    ??=endif /* _MAP_ */

0
фрилансер
 Аватар для Алексей1153
6461 / 5663 / 1130
Регистрация: 11.10.2019
Сообщений: 15,079
10.12.2019, 13:26
ого, триграфы о_О
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
10.12.2019, 14:04

Не по теме:

d7d1cd, это поведение, конечно, баг. Я такое встречал в каких-то других реализациях, дело было давно.



Добавлено через 2 минуты

Не по теме:

Цитата Сообщение от d7d1cd Посмотреть сообщение
Dinkum C++ Library
А, ну да. Это та же реализация, что была в VS 6 )

1
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
10.12.2019, 14:19  [ТС]
Цитата Сообщение от DrOffset Посмотреть сообщение
это поведение, конечно, баг
Ну слава яйцам, что для читающих разъяснена причина моего негодования и заведения этой темы.
Надеюсь, реализация заплатки годная...
1
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
10.12.2019, 14:31
Цитата Сообщение от d7d1cd Посмотреть сообщение
Скажите, а нельзя ли типы базового класса использовать напрямую?
Можно их протащить через using.
C++
1
2
  using typename base::mapped_type;
  using typename base::key_type;
Добавлено через 3 минуты

Не по теме:

Цитата Сообщение от d7d1cd Посмотреть сообщение
для читающих разъяснена причина
Практика показывает, что обычно этого бывает мало. :)
Кого-то может еще поубеждать придется, страниц 10. Но я в этот раз пас.

0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
10.12.2019, 15:17
d7d1cd, эта библиотека написана корифеями. Вот как плохо жиреть на военных заказах... Я бы предложил отказаться от оператора индексации. И обязательно искать, сначала (см. выше).
Можно ещё поработать с указателями в качестве значений (придётся написать предикат на сравнение указателей) и переписать всё, что работало со значениями. Поэтому проще предварять insert поиском и использовать итератор подсказки если пара не найдена (upper_bound) и если найдена то удаляем её и вставляем новую или переписываем значение в паре, в зависимости от поддержки в классе значения. Тут также, есть выбор, - оставить прежнее без изменения, чего оператор[] не предоставляет. Это должно работать быстрее чем оператор [].
0
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
10.12.2019, 15:25  [ТС]
IGPIGP, скажите, а чем плох метод переопределения оператора []?
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
10.12.2019, 15:55
Цитата Сообщение от d7d1cd Посмотреть сообщение
IGPIGP, скажите, а чем плох метод переопределения оператора []?
Это как?
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
10.12.2019, 15:59
d7d1cd, я вам даже больше скажу, во времена, когда ваша версия компилятора и библиотеки были актуальными - в С++ сообществе вовсю практиковалась замена STD на стороннюю, потому что стандартная часто не выдерживала критики.

Так родился, например, такой продукт как STLPort, ныне почти полностью позабытый.
1
495 / 209 / 70
Регистрация: 27.05.2016
Сообщений: 557
10.12.2019, 16:27
Цитата Сообщение от d7d1cd Посмотреть сообщение
То есть, сделать поведение оператора [] в мапе таким же как в подавляющем большинстве реализациях STL - плохое решение?
Решение годное
Искал инфу с доводами против наследования от стандартных STL контейнеров - есть те кто считает это неправильным в силу того что стандартные контейнеры не проектировались для наследования (у них нет, как минимум, виртуальных деструкторов), а есть и те кто считает это нормальной практикой. Нужно смотреть под какие нужды это делаеться и как будет использоваться и не возникнет ли в будущем проблем при работе с таким кодом. Кстати: boost program_options variables_map
1
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
10.12.2019, 16:50
Я не знаю кто вбросил эту мысль про отсутствие виртуальных деструкторов как критерий неиспользования в качестве базовых классов, но эта дурь ходит по сети лет 20 точно. И каждое новое поколение новичков постоянно на это ссылается.

А дурь это потому, что для того, чтобы виртуальный деструктор имел значение - класс должен предполагать полиморфное использование. И мало того, полиморфное удаление. У стандартных контейнеров нет ни одного виртуального метода, значит никакого полиморфного использования с ними не получится априори. И довод, что кто-то может сделать так:
C++
1
2
3
std::string * p = new my_stdstring();
 
delete p;
просто не выдерживает критики, потому что чтобы такое написать нужно быть свято уверенным в полиморфном использовании std::string. Учитывая, что этого никто никогда не предполагал в дизайне класса, то это выглядит так же странно, как любая другая UB-провоцирующая дичь, которую можно написать на С++, если задаться такой целью. Например можно сказать, что массивы в С++ не предназначены для индексации, потому что любой может написать код, выходящий за его пределы.

Более того, если бы комитет поддерживал эту идею, то с приходом С++11 давно бы уже по-объявляли все стандартные контейнеры как final и закрыли вопрос. Но никто что-то этого делать не стал.
5
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
10.12.2019, 16:50
Цитата Сообщение от notAll Посмотреть сообщение
а есть и те кто считает это нормальной практикой. Нужно смотреть под какие нужды это делаеться и как будет использоваться и не возникнет ли в будущем проблем при работе с таким кодом.
Там два параметра типа по умолчанию. Я пробовал наследоваться от контейнеров (от vector в частности) и оно получалось несколько неровно. Хотелось бы посмотреть хороший пример.
Кроме того, придётся перекомпилировать весь проект. Это иногда критический затык. Ну а проблемы с совместимостью с библиотеками, которые могут юзать этот класс и перспективой расширения кодовой базы тоже не радостны. Я бы не стал так делать. Можно переписать все критические места где вызывается оператор индексации и оно будет работать на всех компиляторах. Но это частное мнение, возможно есть варианты получше.
0
279 / 156 / 52
Регистрация: 30.06.2011
Сообщений: 1,712
11.12.2019, 08:37  [ТС]
Цитата Сообщение от IGPIGP Посмотреть сообщение
Это как?
Вот так.

IGPIGP, по Вашему последнему посту. Я меняю поведение оператора [] в мапе только для использования в своем проекте. Этот проект будет и может работать только на конкретной системе. Код в стандартной библиотеке я не меняю (да и нет у меня авторизации на изменение этих файлов).
Планирую все подобные баги STL в моей системе исправлять (видимо, как и тут, создавать наследников с переопределением кривых методов) и хранить в отдельных файлах. При необходимости использовать в заголовках их.
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
11.12.2019, 08:48
d7d1cd, а если рассмотреть вариант полной замены STL на ту же STLPort? Она не только содержит меньше багов, но еще и быстрее работает. Если весь проект пересадить на нее, то он, возможно, станет работать лучше.
0
Комп_Оратор)
Эксперт по математике/физике
 Аватар для IGPIGP
9007 / 4708 / 630
Регистрация: 04.12.2011
Сообщений: 14,003
Записей в блоге: 16
11.12.2019, 12:34
Цитата Сообщение от d7d1cd;14 083250
Это как?
Вот так.
d7d1cd, это не переопределение оператора. Это наследование. И я хотел бы видеть вариант как можно унаследовать от std::map чтобы сохранить свободу выбора предикат и аллокатора (два параметра типа по умолчанию.
Вы думаете без компаратора, карта не будет ущербна?
Лучше уже затайпдефить карту каким-то промежуточным типом. Включить тайпдеф в условных директивах так чтобы можно было компилировать и так и эдак. И в варианте "'эдак" использовал бы включение объекта map. Да, - придётся переписать кучу тупого обёрточного кода. Но это не так уж и долго.

Добавлено через 37 минут
Но в принципе, я вас немного запутал. При прямом наследовании можно конечно похулиганить. Но стрёмно как-то
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
template <class Key_t, class Val_t,
class Copmar_t= std::less<Key_t >,
class Alloc_t= std::allocator<std::pair<const Key_t, Val_t > > >
class DerivedMap : public std::map<Key_t, Val_t, Copmar_t, Alloc_t >
{
    public:
    DerivedMap()
    :std::map<Key_t, Val_t, Copmar_t, Alloc_t >()
    {
 
    }
};
 
int main()
{
DerivedMap<int,int> dmap;
dmap[1]=2;
std::cout<<dmap[1]<<std::endl;
return 0;
}
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
11.12.2019, 12:40
Цитата Сообщение от IGPIGP Посмотреть сообщение
И я хотел бы видеть вариант как можно унаследовать от std::map чтобы сохранить свободу выбора предикат и аллокатора
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
template<typename Key, typename Tp, typename Comp = std::less<Key>, typename Alloc = std::allocator<std::pair<const Key, Tp> > >
class map_ex : public std::map<Key, Tp, Comp, Alloc>
{
    typedef std::map<Key, Tp, Comp, Alloc> base;
public:
    using typename base::key_type;
    using typename base::mapped_type;
    using typename base::value_type;
    using typename base::key_compare;
    using typename base::allocator_type;
    
    map_ex()
      : base() 
    {}
    explicit map_ex(const key_compare & comp, const allocator_type & a = allocator_type())
      : base(comp, a) 
    {}
    map_ex(const map_ex & x)
      : base(x) 
    {}
    
    // ....
};
как-то так (с++03).
3
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
11.12.2019, 12:40
Помогаю со студенческими работами здесь

Обход элементов std::map в порядке их создания
Имеется ассоциативный массив и его заполнение: std::map&lt;unsigned,string&gt; arr; arr = &quot;abc&quot;; arr = &quot;def&quot;; arr =...

std::string, std::fstream, ошибка кучи
где то начало вылетать при операции += с локальной переменной std::string. Заменил на свой qString. Замечательно, то же самое... ошибка при...

Как проинициализировать std::stack<const int> obj ( std::stack<int>{} );
добрый день. вопрос в коде: http://rextester.com/VCVVML6656 #include &lt;iostream&gt; #include &lt;stack&gt; //-std=c++14...

std::filesystem && std::asio и пр
Пытался найти хоть какие-то сроки включения всего этого в стандарт (так же ожидается lexical_cast, any, string_algo и т.д.) и вообщем везде...

Где в настройках RAD Studio 10 Seattle изменить аргумент на -std=c99?
ребята, где в настройках RAD Studio 10 Seattle изменить аргумент на -std=c99 , что бы компилятор не выдавал ошибок


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

Или воспользуйтесь поиском по форуму:
40
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11680&amp;d=1772460536 Одним из. . .
Реалии
Hrethgir 01.03.2026
Нет, я не закончил до сих пор симулятор. Эта задача сложнее. Не получилось уйти в плавсостав, но оно и к лучшему, возможно. Точнее получалось - но сварщиком в палубную команду, а это значит, в моём. . .
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
SDL3 для Web (WebAssembly): Сборка библиотек: SDL3, Box2D, FreeType, SDL3_ttf, SDL3_mixer и SDL3_image из исходников с помощью CMake и Emscripten
8Observer8 27.02.2026
Недавно вышла версия 3. 4. 2 библиотеки SDL3. На странице официальной релиза доступны исходники, готовые DLL (для x86, x64, arm64), а также библиотеки для разработки под Android, MinGW и Visual Studio. . . .
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru