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?
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..
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 learning C++ and can't get my head around this problem:
I have a simple class A
class A {
private:
int ival;
float fval;
public:
A(int i = 0, float f = 0.0) : ival(i), fval(f) { }
~A(){ }
void show() const {
cout << ival << " : " << fval << "\n";
}
void setVal(int i) {
ival = i;
}
//const getters for both ival and fval
//used for the default "lesser"
friend bool operator<(const A& val1, const A& val2) {
return val1.ival < val2.ival ? true : false;;
}
}
Then I have a regular set<A> myset that gets filled with insert(A(2, 2.2)); in a loop.
Iterating to get all the values is not a problem but I want to modify the value within this iteration:
for(set<A>::iterator iter = set3.begin(); iter != set3.end(); iter++) {
iter->setVal(1);
}
I assume that this should be doable, like you would do it in Java within a foreach loop. When compiling I get error: passing ‘const A’ as ‘this’ argument of ‘void A::setVal(int)’ discards qualifiers.
Looking at the sources of the STL set, i see that begin() is only available as a const method and I think this might be the problem. Messing around with const on the setVal() method got always the same error and wouldn't make much sense since I want to modify the value of A.
Is this the wrong approach of changing a bunch of A's values with a loop?
The STL set does not let you change values it stores. It does that by returning a copy of the object through the iterator (not the actual one in the set).
The reason that set does this is because it's using < to order the set and it doesn't want to remake the entire tree every time you dereference the iterator, which it would have to do, since it doesn't know if you changed anything that changes the ordering.
If you need to update the set<>, remove the old value and add in a new one.
EDIT: just checked source to SGI STL and it says this:
typedef typename _Rep_type::const_iterator iterator;
So, a set::iterator is just a set::const_iterator
From this page, it seems that begin() exists as well as a non-const method.
Perhaps your set is passed into the method as a const reference ?
EDIT
The referenced page is wrong. As Scharron states, there is no non-const begin() (or end() for that matter) method for ordered containers.
I will inform the website about their mistake (it's not the first they made ;))
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.
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.