0

Possible Duplicate:
C++ STL set update is tedious: I can't change an element in place

I want to use a std::set<> to count the number occurences of a certain value and simultaneosly sort the objects. For this I created a class RadiusCounter

class RadiusCounter
{
public:
    RadiusCounter(const ullong& ir) : r(ir) { counter = 1ULL; }
    void inc() { ++counter; }
    ullong get() const { return counter;}
    ullong getR() const { return r;}
    virtual ~RadiusCounter();
protected:
private:
    ullong r;
    ullong counter;
};

(the destructor does nothing) together with comparison operators:

const inline bool operator==(const RadiusCounter& a, const RadiusCounter& b) {return  a.getR() == b.getR();}
const inline bool operator< (const RadiusCounter& a, const RadiusCounter& b) {return a.getR() < b.getR();}
const inline bool operator> (const RadiusCounter& a, const RadiusCounter& b) {return a.getR() > b.getR();}
const inline bool operator!=(const RadiusCounter& a, const RadiusCounter& b) {return a.getR() != b.getR();}
const inline bool operator<=(const RadiusCounter& a, const RadiusCounter& b) {return a.getR() <= b.getR();}
const inline bool operator>=(const RadiusCounter& a, const RadiusCounter& b) {return a.getR() >= b.getR();}

now I want to use it like this:

set<RadiusCounter> theRadii;
....
ullong r = getSomeValue();

RadiusCounter ctr(r);
set<RadiusCounter>::iterator itr = theRadii.find(ctr);

// new value -> insert
if (itr == theRadii.end()) theRadii.insert(ctr);

// existing value -> increase counter
else itr->inc();

But now the compiler complains at the line with the call to itr->inc():

error: passing 'const RadiusCounter' as 'this' argument of 'void RadiusCounter::inc()' discards qualifiers

Why is the instance in *itr a const here?

Community
  • 1
  • 1
Thomas
  • 1,160
  • 3
  • 16
  • 34

3 Answers3

10

Because you can't modify elements in a std::set. If you could, it would allow the possibility that it would break the strict-weak ordering invariant, resulting in undefined behaviour.

If you want to modify an element, then you should erase the element, and insert a new one.

Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
3

As addition, it seems you want just

typedef int Radius;
typedef int Counter
std::map<Radius, Conunter>theRadii;

...

theRadii[getSomeValue()]++;
Lol4t0
  • 12,444
  • 4
  • 29
  • 65
1

As it happens I already answered this question a few hours ago: https://stackoverflow.com/a/9452445/766580. Basically, you can't change the value of a set element because the set has no way of knowing what you changed. You will need to remove and reinsert your modified value if you want to do this.

Community
  • 1
  • 1
spencercw
  • 3,320
  • 15
  • 20
  • Please flag the question as a duplicate if you find something like this. As it stands, your answer isn't really an answer, it's just a link to some place else. – Mat Feb 26 '12 at 17:07