Help! iterator problem

Started by
12 comments, last by kauna 10 years, 3 months ago

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;
}

Advertisement
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()'.

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.

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;}

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!

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?

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.


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.


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.

Stephen M. Webb
Professional Free Software Developer

This topic is closed to new replies.

Advertisement