Начиная с Visual Studio 2010, итерация по набору, по-видимому, возвращает итератор, который разыменовывает данные как «константные данные», а не как неконстантные.
Следующий код является примером того, что компилируется в Visual Studio 2005, но не в 2010 (это искусственный пример, но он ясно иллюстрирует проблему, которую мы обнаружили в нашем собственном коде).
В этом примере у меня есть класс, который хранит позицию вместе с температурой. Я определяю операторы сравнения (не все, достаточно для иллюстрации проблемы), которые используют только положение, а не температуру. Дело в том, что для меня два экземпляра идентичны, если позиция идентична; Меня не волнует температура.
#include <set>
class DataPoint
{
public:
DataPoint (int x, int y) : m_x(x), m_y(y), m_temperature(0) {}
void setTemperature(double t) {m_temperature = t;}
bool operator<(const DataPoint& rhs) const
{
if (m_x==rhs.m_x) return m_y<rhs.m_y;
else return m_x<rhs.m_x;
}
bool operator==(const DataPoint& rhs) const
{
if (m_x!=rhs.m_x) return false;
if (m_y!=rhs.m_y) return false;
return true;
}
private:
int m_x;
int m_y;
double m_temperature;
};
typedef std::set<DataPoint> DataPointCollection;
void main(void)
{
DataPointCollection points;
points.insert (DataPoint(1,1));
points.insert (DataPoint(1,1));
points.insert (DataPoint(1,2));
points.insert (DataPoint(1,3));
points.insert (DataPoint(1,1));
for (DataPointCollection::iterator it=points.begin();it!=points.end();++it)
{
DataPoint &point = *it;
point.setTemperature(10);
}
}
В основной подпрограмме у меня есть набор, к которому я добавляю несколько точек. Чтобы проверить правильность оператора сравнения, я добавляю точки данных с одной и той же позицией несколько раз. При написании содержимого набора я четко вижу, что в наборе всего 3 точки.
Цикл for проходит по набору и устанавливает температуру. Логически это разрешено, так как температура не используется в операторах сравнения.
Этот код корректно компилируется в Visual Studio 2005, но выдает ошибки компиляции в Visual Studio 2010 в следующей строке (в цикле for):
DataPoint &point = *it;
Указанная ошибка заключается в том, что он не может назначить «const DataPoint» [неконстантному] «DataPoint &».
Кажется, что у вас нет приличного (= не грязного) способа написания этого кода в VS2010, если у вас есть оператор сравнения, который сравнивает только части элементов данных.
Возможные решения:
- Добавление const-cast в строку, где выдает ошибку
- Сделать температуру изменяемой и сделать setTemperature константным методом
Но мне оба решения кажутся довольно «грязными».
Похоже, комитет по стандартам C++ проглядел эту ситуацию. Или нет?
Каковы чистые решения для решения этой проблемы? Кто-нибудь из вас сталкивался с такой же проблемой и как вы ее решили?
Патрик