Starting from Visual Studio 2010, iterating over a set seems to return an iterator that dereferences the data as 'const data' instead of non-const.
The following code is an example of something that does compile on Visual Studio 2005, but not on 2010 (this is an artificial example, but clearly illustrates the problem we found on our own code).
In this example, I have a class that stores a position together with a temperature. I define comparison operators (not all them, just enough to illustrate the problem) that only use the position, not the temperature. The point is that for me two instances are identical if the position is identical; I don't care about the temperature.
#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);
}
}
In the main routine I have a set to which I add some points. To check the correctness of the comparison operator, I add data points with the same position multiple times. When writing the contents of the set, I can clearly see there are only 3 points in the set.
The for-loop loops over the set, and sets the temperature. Logically this is allowed, since the temperature is not used in the comparison operators.
This code compiles correctly in Visual Studio 2005, but gives compilation errors in Visual Studio 2010 on the following line (in the for-loop):
DataPoint &point = *it;
The error given is that it can't assign a "const DataPoint" to a [non-const] "DataPoint &".
It seems that you have no decent (= non-dirty) way of writing this code in VS2010 if you have a comparison operator that only compares parts of the data members.
Possible solutions are:
- Adding a const-cast to the line where it gives an error
- Making temperature mutable and making setTemperature a const method
But to me both solutions seem rather 'dirty'.
It looks like the C++ standards committee overlooked this situation. Or not?
What are clean solutions to solve this problem? Did some of you encounter this same problem and how did you solve it?
Patrick