Sign in to follow this  

Help! iterator problem

This topic is 1439 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Folks,

 

I am working on my orbital flight simulator in C++ language.  I tried to implement find function call in class StarDatabase but encountered two blocking error messages. With using 'iterator', compiler complained about 'no match for operator ='.  I changed to 'const_iterator' and it worked but complaint 'invalid conversion from const to non const' at return statement.  That's why I want to return non const Star class to the caller to update it.  Does anyone know any solution or working around.

 

Look at my code below.

 

Thanks,

Sword7

std::vector<Star> unsortedStars;
Star *StarDatabase::find(uint32 catalogNumber) const
{
	std::vector<Star>::iterator iter;
	for (iter = unsortedStars.begin(); iter != unsortedStars.end(); iter++) {
		if ((*iter).getCatalogNumber() == catalogNumber)
			return &(*iter);
	}
	return NULL;
}

Share this post


Link to post
Share on other sites
Why does your function return a non-const pointer to data from a const container? (I assume `unsortedStarts' is a member of StarDatabase).

Readability tip: You can use `iter->getCatalogNumber()' instead of `(*iter).getCatalogNumber()'.

Share this post


Link to post
Share on other sites

Ok, I figured them out.  I decided to remove 'const' from function call and all problems were gone.

 

Non const iterator did not work in const function calls because compiler complaint about 'no match for operator =' error messages at for(...) statement.

 

I am using MinGW with GNU C++ 4.8.2 compiler.

Share this post


Link to post
Share on other sites

In order to use the const in the function definition, you'll need to use a const iterator too. 

 

I'd keep the const in the find function since typically you don't expect a function called "find" to change the object in any way. 

 

Const correctness is important and it is rather boring to correct the constness of a huge code base afterwards.

 

Cheers!

Share this post


Link to post
Share on other sites

 

You can also use

std::find(unsortedStars.begin(), unsortedStars.end(), catalogNumber);

if you supply a

bool operator ==(const Star &s, uint32 c) { return s.getCatalogNumber() == c;}

Make it a lambda, or a function object that explicitly specifies what it compares, instead of a generic operator. A generic comparison between a star and an integer is fairly arbitrary and requires some additional semantics that motivates why the integer is specifically compared to the star's catalog number. If the integer can logically compare to other attributes of a star, then you have just locked the generic comparison to catalog numbers only by specifying a generic comparison operator.

 

std::find(unsortedStars.begin(), unsortedStars.end(), [=](Star const & s) {
    return s->getCatalogNumber() == catalogNumber;
});

 

Operators between user defined types and something else, in particular built in types, should be used with care. Well established operations such as vector/scalar multiplication may be OK, since there are not many different sensible things you can do with a vector, a scalar and a multiplication. But the more complex a type becomes, the more specific an operation becomes; what common operations can you do with a star, an integer and a comparison operator?

Share this post


Link to post
Share on other sites

In order to use the const in the function definition, you'll need to use a const iterator too. 

 

I'd keep the const in the find function since typically you don't expect a function called "find" to change the object in any way. 

 

Const correctness is important and it is rather boring to correct the constness of a huge code base afterwards.

 

Cheers!

 

In order for that to work he has to change the return value to const Star *.  The compiler correctly complained when he didn't because returning a non-const pointer to internal data from a const member function is still violating const correctness because the internal data can then be changed outside the class itself.  Since he wants the pointer specifically to change that internal data, the member function should not be declared const, at which point nothing else needs to be const.

Share this post


Link to post
Share on other sites

 


In order for that to work he has to change the return value to const Star *

 

As far as I know, that won't be necessary. It is perfectly ok for a const function to return a copy of a member variable. In this case the copy happens to be a pointer.

 

Cheers!

 

You cannot return a non-const pointer to internal data from a function that is const. The non-const poiner allows you to alter the internal state of the object via a member function that promised that no observable change is allowed. In this case, you're not returning a copy of an internal pointer value, you are returning a pointer to internal data.

Share this post


Link to post
Share on other sites


You cannot return a non-const pointer to internal data from a function that is const. The non-const poiner allows you to alter the internal state of the object via a member function that promised that no observable change is allowed. In this case, you're not returning a copy of an internal pointer value, you are returning a pointer to internal data.

I am having trouble finding anything in the standard to back that up.  In fact, there is no way for the language to enforce that, since it would require semantic knowledge about non-local usage of a copied value.

 

I can see that if you do use the returned copy of the pointer to alter the internal state of a const object, you could be treading the grounds of undefined behaviour.  I see nothing in C++ that disallows you from doing that.

Share this post


Link to post
Share on other sites

 


You cannot return a non-const pointer to internal data from a function that is const. The non-const poiner allows you to alter the internal state of the object via a member function that promised that no observable change is allowed. In this case, you're not returning a copy of an internal pointer value, you are returning a pointer to internal data.

I am having trouble finding anything in the standard to back that up.  In fact, there is no way for the language to enforce that, since it would require semantic knowledge about non-local usage of a copied value.

 

I can see that if you do use the returned copy of the pointer to alter the internal state of a const object, you could be treading the grounds of undefined behaviour.  I see nothing in C++ that disallows you from doing that.

 

If you have a member of type T in a class, then just make it of type const T in a const member function so you cannot convert it to a T*, only const T*, by taking its address. That would make sure that you cannot modify the internal state via the pointer returned by the const member function.

Share this post


Link to post
Share on other sites

 

 


You cannot return a non-const pointer to internal data from a function that is const. The non-const poiner allows you to alter the internal state of the object via a member function that promised that no observable change is allowed. In this case, you're not returning a copy of an internal pointer value, you are returning a pointer to internal data.

I am having trouble finding anything in the standard to back that up.  In fact, there is no way for the language to enforce that, since it would require semantic knowledge about non-local usage of a copied value.

 

I can see that if you do use the returned copy of the pointer to alter the internal state of a const object, you could be treading the grounds of undefined behaviour.  I see nothing in C++ that disallows you from doing that.

 

If you have a member of type T in a class, then just make it of type const T in a const member function so you cannot convert it to a T*, only const T*, by taking its address. That would make sure that you cannot modify the internal state via the pointer returned by the const member function.

 

 

Isn't that what actually happens if you try to circumvent const protections?

 

struct X {
  X(int data) : data(data) {
  }
 
  int data;
 
  int *get_data() const {
    return &data;
  }
};

 

The compiler barfs like this:

kk.cpp: In member function ‘int* X::get_data() const’:
kk.cpp:8:13: error: invalid conversion from ‘const int*’ to ‘int*’ [-fpermissive]

 

Or are we talking about something else?

Share this post


Link to post
Share on other sites

Sorry,

 

I didn't notice that the missing * in the original post.

 

If the container contained pointers to objects such as std::vector<Star*> unsortedStars; then there shouldn't be a problem.

 

Cheers!

Share this post


Link to post
Share on other sites

This topic is 1439 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this