Ссылки константы при разыменовании итератора на наборе, запуске с Visual Studio 2010

Запуск с 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 точки.

Циклы для цикла по набору и наборам температура. Логически это позволяется, так как температура не используется в операторах сравнения.

Этот код компилирует правильно в Visual Studio 2005, но дает ошибки компиляции в Visual Studio 2010 на следующей строке (в для цикла):

   DataPoint &point = *it;

Данная ошибка состоит в том, что это не может присвоить "константе DataPoint" [неконстанта] "DataPoint и".

Кажется, что Вы имеете не достойный (= негрязный) способ написать этот код в VS2010, если у Вас есть оператор сравнения, который только сравнивает части элементов данных.

Возможные решения:

  • Добавление брошенного константой к строке, где это дает ошибку
  • Создание изменяемой температуры и создание setTemperature метод константы

Но мне оба решения кажутся довольно 'грязными'.

Похоже, что комитет по стандартам C++ пропустил эту ситуацию. Или нет?

Что чистые решения состоят в том, чтобы решить эту проблему? Некоторые из Вас встречались с этой той же проблемой и как Вы решали ее?

Patrick

11
задан Patrick 26 March 2010 в 12:19
поделиться

3 ответа

Итератор должен давать вам константную ссылку (и это то, что в Стандарте сказано, что он должен do), потому что изменение упомянутой вещи нарушит действительность базовой структуры данных набора - набор не «знает», что поле, которое вы изменяете, на самом деле не является частью ключа. Альтернативой является внесение изменений путем удаления и повторного добавления или использование вместо этого std :: map.

13
ответ дан 3 December 2019 в 08:28
поделиться

Если вы не хотите удалять и добавлять заново, как предлагает Нил, вы можете сделать setTemperature const и m_temperature mutable.

0
ответ дан 3 December 2019 в 08:28
поделиться

Set должен возвращать итератор const, потому что он не знает, могут ли функции-члены изменить упорядочение.

Похоже, что вам действительно нужна карта, где вы сопоставляете неизменяемый ключ (x, y) с переменной температурой.

0
ответ дан 3 December 2019 в 08:28
поделиться
Другие вопросы по тегам:

Похожие вопросы: