Reputation: 11
class Test
{
private:
int v;
public:
Test(int h)
{
v = h;
}
int getV()
{
return v;
}
bool operator < (const Test& b) const
{
return v < b.v;
}
};
int main()
{
set <Test> st;
for(int i = 1; i <= 10; i++)
{
Test t(i);
st.insert(t);
}
for(set<Test>::iterator it = st.begin(); it != st.end(); it++)
{
cout << (*it).getV() << endl;
//Test it2 = *it;
//cout << it2.getV() << endl;
}
return 0;
}
It will be
|error: passing 'const Test' as 'this' argument of 'int Test::getV()' discards qualifiers [-fpermissive]|
but if I use Test it2 = *it; cout << it2.getV() << endl;
, it will work well. Why does it use the words 'const Test' and why the code can't work?
Upvotes: 0
Views: 67
Reputation: 5387
Another way is to remove the constness of the object refereed by the iterator. In that case, getV doesn't need to be a const method. Check the modified code below:
for(set<Test>::iterator it = st.begin(); it != st.end(); it++)
{
cout << (const_cast<Test*>(&(*it)))->getV() << endl;
//Test it2 = *it;
//cout << it2.getV() << endl;
}
I don't understand why the above answer was down-voted. I just gave an example of doing it another way. In some cases we have to do that. There are times when we need to set some value in the object. Can the down-voters kindly see the reasons looking at the below example:
#include <iostream>
#include <set>
using namespace std;
class Test
{
private:
int v;
int w;
public:
Test(int h, int i)
{
v = h;
w = i;
}
int getV() const
{
return v;
}
int getW() const
{
return w;
}
void setW(int a) // This will not screw up the set as only v is used for comparison
{
w = a;
}
// Operator < is not using only v for comparison
// of objects and not using w for that purpose
bool operator < (const Test& b) const
{
return v < b.v;
}
};
int main()
{
set <Test> st;
for(int i = 10; i >= 0; i--)
{
Test t(i, i);
st.insert(t);
}
for(set<Test>::iterator it = st.begin(); it != st.end(); it++)
{
const_cast<Test*>(&(*it))->setW(1000);
}
for(set<Test>::iterator it = st.begin(); it != st.end(); it++)
{
cout << it->getV() << " " << it->getW() << endl;
}
return 0;
}
Upvotes: -3
Reputation: 340228
A set
iterator is a const iterator. You'll need to mark getV()
as const (which it should be anyway since it doesn't change the object):
int getV() const // <--
{
return v;
}
Upvotes: 1
Reputation: 88185
std::set
iterators return const references because set
s are sorted, and if you change the value of an object in a set then it could be in the wrong position for the new value. That could make the object un-findable and worse.
When you do
Test it2 = *it;
You're making a copy of the object, and you can modify the copy as much as you like. You can't mess up the set
by modifying the copy.
The problem is that your getV()
method is not correctly const qualified. It should be:
int getV() const
{
return v;
}
And then the first code will compile and work just fine.
Failing to apply const where it's correct will often cause these kinds of problems. You should work to correctly apply const-qualificiations.
Upvotes: 6