Having problems iterating. Problem has to do with const correctness, I think. I assume B::getGenerate() should be const for this code to work, but I don't have control over B::getGenerate().
Any help is greatly appreciated.
Thanks in advance,
jbu
Code follows:
int
A::getNumOptions() const
{
int running_total = 0;
BList::const_iterator iter = m_options.begin();
while(iter != m_options.end())
{
if(iter->getGenerate()) //this is the line of the error; getGenerate() returns bool; no const in signature
{
running_total++;
}
}
return running_total;
}
1>.\A.cpp(118) : error C2662: 'B::getGenerate()' : cannot convert 'this' pointer from 'const B' to 'B &'
Well, if getGenerate is non-const, your iterator must be non-const. And if that's the case, your getNumOptions will also have to be non-const.
If getGenerate isn't under you control, there isn't anything else you can do. But if that method could be const, bring it up with whoever implemented that method; tell them it should be const.
B::getGenerate() needs to be declared like this:
class B
{
bool getGenerate() const;
};
The 'const' keyword is the important bit here. This tells the compiler that calling getGenerate() will not modify any of the other members of B.
Related
Can anyone explain to me why the following segment compiles but the commented line after doesn't?
struct tObj
{
int data;
int moreData;
}
...
void funcToCall (tObj *obj, int moreData)
{
//Useful stuff here
}
void mainFunction ()
{
vector<tObj>::iterator it = vectorOfObjects.begin(); //assumes vectorOfObjects is already defined
while (it != vectorOfObjects.end())
{
funcToCall (&(*it), 0); //This line works
funcToCall (it, 0); //This line produces an error
it++;
}
}
The error produced is this:
error: cannot convert ‘std::vector<tObj>::iterator {aka __gnu_cxx::__normal_iterator<tObj*, std::vector<tObj> >}’ to ‘tObj*’
Any ideas on why &(*it) works but just plain it doesn't? Logically they are the same, aren't they?
Because doesn't * mean to dereference and & mean pass by reference aka cancelling each other out?
it is an iterator object, passing it as-is would mean you're trying to pass an object of type vector<tObj>::iterator for a function expecting tObj*, and thus the error.
When you do *it you'd get the underlying object the iterator is representing and when you apply & atop that, you get that object's address, which is of type tObj* which agrees with the function's argument type and thus no error.
That the code would be compiled you have to declare an overloaded function like
void funcToCall ( std::vector<tObj>::iterator it, int moreData)
{
//Useful stuff here
}
In general case types tObj * and vector<tObj>::iterator are different types though in some old realizations of std::vector its iterator is indeed defined as a pointer..
I am trying to use a list for my bullets.
Whenever I run my update bullet code it gives me this error:
Error 1 error C2662: 'Bullet::detectCollision' : cannot convert 'this' pointer from 'const Bullet' to 'Bullet &'
my list:
std::list<Bullet> bullet_list;
my update code:
std::list<Bullet>::const_iterator cIter;
for ( cIter = bullet_list.begin( ); cIter != bullet_list.end( ); cIter++ )
{
if((*cIter).detectCollision(monster.position,monster.getHeight(),monster.getWidth()))
{
//Do stuff here
}
if ((*cIter).detectCollision(boss.getPosition(),boss.getHeight(),boss.getWidth()))
{
//Do stuff here
}
}
my detect collision code:
bool Bullet::detectCollision(Vector objTwo,int heightT,int widthT)
{
if(position.getVectorX() >= objTwo.getVectorX() - (widthT/2) && position.getVectorX() <= objTwo.getVectorX() + (widthT/2)
&& position.getVectorY() >= objTwo.getVectorY() - (widthT/2)&& position.getVectorY() <= objTwo.getVectorY() + (heightT/2) && alive)
{
return false;
}
return true;
}
You need to declare detectCollision as const.
bool Bullet::detectCollision(Vector objTwo,int heightT,int widthT) const
When you don't, it's trying to do a conversion so it can call a non-const function on a const reference but it's not allowed.
You are using const_iterator but trying to access a non-const member function. Either use iterator instead of the const_iterator or declare the function as const if it can be a const member function.
A const_iter does not allow the values it points at to be changed, so when you're calling detectCollision you need to promise the compiler you also won't change those values(make the function const).
I have a problem passing a map<...>::iterator object to a function as a const_iterator & on GCC:
class MyClass {
};
bool MyClass::_GetInstList(map<string,InstList>::const_iterator & it, const string & sMod)
{
cout<<"Matched\n";
it = tInstancesData.find(sMod);
if( it == tInstancesData.end() ) {
cout<<"\""<<sMod<<"\" is NOT a module\n";
return false;
}
return true;
}
bool SomeFunction()
{
map<string,InstList>::iterator it;
if( ! _GetInstList(it, SomeString) ) return false;
it->second.Add(...); // Modifying element pointed by "it"
}
My probelm is that on Visual Studio 2010 the code above works perfectly fine, but on GCC 4.1.2 I get an error saying there is no matching function to the function call, for _GetInstList(it, SomeString). The issue seems to be converting iterator to const_iterator &.
I have to take it by reference because "it" gets changed inside _GetInstList() and the caller function checks it. (The "it" pointer is changed not a pointed element).
Also, the "it" in SomeFunction() cannot be const because it changes an element.
How can I resolve this?
EDIT:
For those who suggest that the problem is the conversion from iterator to const_iterator:
The code compiles fine if the function prototype is changed to take const_iterator NOT as a reference, the problem is the const &.
Change your argument type to const map<string,InstList>::const_iterator& or just a map<string,InstList>::const_iterator.
Here's an example demonstrating your problem (and the solution) with simple types:
void func1(double& x){}
void func2(const double& x){}
int main()
{
int x;
func1(x); // error: 'func1' : cannot convert parameter 1 from 'int' to 'double &'
func2(x); // succeeds
}
I think maybe this method should be redesigned anyway. Passing iterators around is messy and confusing for others to read. How hard would it be to do that?
Updated
This is the method that gives me trouble:
void A::normalizeUrls()
{
for (set<CUrl>::iterator it = _references.begin(); it != _references.end(); ++it)
{
if (it->isValid())
{
it->normalize().makeFull(_baseUrl);
}
}
}
And here are CUrl::normalize and CUrl::makeFull
CUrl& makeFull (CUrl&)
{
return *this;
}
CUrl& CUrl::normalize()
{
return *this;
}
The errors are: CUrl::normalize' : cannot convert 'this' pointer from 'const CUrl' to 'CUrl &'
left of '.makeFull' must have class/struct/union
Why is that so, what am I missing?
Thanks in advance!
auto will drop references. I don't know if auto& works, but if not you'll have to specify CUrl& explicitly.
In practice, the members of a set are const (immutable), so you cannot call non-const member functions on them.
If that was allowed, you might change their values and invalidate the ordering of the set.
It seems that the _references.begin() call is returning a const_iterator instead of a regular iterator. Is the _references variable a const reference to the set?
It's definitely a problem with the const status of the iterator, though. The following code compiles:
if (it->isValid())
{
CUrl &ref = const_cast<CUrl&>(*it);
ref.normalize().makeFull(_baseUrl);
}
I'm trying to get a pointer to a specific version of an overloaded member function. Here's the example:
class C
{
bool f(int) { ... }
bool f(double) { ... }
bool example()
{
// I want to get the "double" version.
typedef bool (C::*MemberFunctionType)(double);
MemberFunctionType pointer = &C::f; // <- Visual C++ complains
}
};
The error message is "error C2440: 'initializing' : cannot convert from 'overloaded-function' to 'MemberFunctionType'"
This works if f is not overloaded, but not in the example above. Any suggestion?
EDIT
Beware, the code above did not reflect my real-world problem, which was that I had forgotten a "const" - this is what the accepted answer points out. I'll leave the question as it is, though, because I think the problem could happen to others.
Well, i'll answer what i put as comment already so it can be accepted. Problem is with constness:
class C
{
bool f(int) { ... }
bool f(double) const { ... }
bool example()
{
// I want to get the "double" version.
typedef bool (C::*MemberFunctionType)(double) const; // const required!
MemberFunctionType pointer = &C::f;
}
};
Clarification:
The original question didn't contain that const. I did a wild guess in the comments whether he possibly has f being a const member function in the real code (because at a yet earlier iteration, it turned out yet another thing was missing/different to the real-world code :p). He actually had it being a const member function, and told me i should post this as an answer.