Avoiding code duplicates in this particular case

Hi!

Consider the following class:

1
2
3
4
5
6
7
8
9
template< typename K, typename T >
class HashMap
{
...
private:
    bool locate( Key a_Key, Bucket       *& a_pBucket );        // Used in the 'add' and 'remove' methods.      
    bool locate( Key a_Key, Bucket const *& a_pBucket ) const;  // Used in the 'contains' method.
...
};

Both 'locate' methods do exactly the same.
To avoid a code duplicate I could use a gigantic macro or const_cast (so I could call the const locate method in the non-const one) but that would be hackish.

Can someone think of a better solution?
You can use a const_cast.
1
2
3
4
5
template< typename K, typename T>
bool HashMap<K, T>::locate( Key a_Key, Bucket *& a_pBucket )
{
	return locate(a_Key, const_cast<Bucket const*&>(a_pBucket));
}
Thanks!

So it's valid to use const_cast in that case?

(I'm just a bit intimidated because I was so often yelled at (figuratively) and told to never use const-cast.)
Last edited on
So it's valid to use const_cast in that case?
No it isn't. Why do you have 2 functions which are doing the same? Remove the non-const function and you should be happy?
My understanding is that it is valid as long as the Bucket object is a non-const object.
No it isn't. Why do you have 2 functions which are doing the same? Remove the non-const function and you should be happy?
I need to have 2 overloads, one const and one non-const, because that private method is called in both const (e.g. 'contains') and non-const (e.g. 'add') methods.

If I removed the non-const version I could not pass a non-const pointer to a Bucket structure as a parameter.

How about you use an iterator instead of a pointer? In that case you could always use the same locate method to find something (make it private!) and return a constant or non-constant iterator depending on what is needed.
How about you use an iterator instead of a pointer? In that case you could always use the same locate method to find something (make it private!) and return a constant or non-constant iterator depending on what is needed.
Thank you!

But I don't really get it. How can one function return both const and non-const iterators?
if I removed the non-const version I could not pass a non-const pointer to a Bucket structure as a parameter.

That's only because you're passing a reference to a non-const pointer to const Bucket.
If your function is not modifying its second argument, it should be const reference:

bool locate( Key a_Key, Bucket const * const & a_pBucket ) const

or just value

bool locate( Key a_Key, Bucket const * a_pBucket ) const
Last edited on
If your function is not modifying its second argument

Thanks, but actually it is the function's main task to modify the second argument (that's why it's called 'locate').

-------

Anyway... I ended up using const_cast, hoping that it's adequate in this case.
Last edited on
It would be better style to make this function return the value it produced rather than use the "out parameter".
It would be better style to make this function return the value it produced rather than use the "out parameter".
Assumed I did that (which I can't for some reason that is not important here), the original problem would still persist.
It doesn't really have anything to do with the iterator, I just said that cause I prefer iterators over pointers - you could do the same thing with a pointer. Basically, let the const version call the non-const version (again, I'm not sure if C++ permits this, cause I never had a situation like that), since you can always safely turn a non-const pointer into a const-pointer that'd be fine. Or you could make it return a hash instead of a pointer, if it's already a hashmap - in that case you wouldn't even need 2 versions.
let the const version call the non-const version
Nope, you can't do that. The non-const version could modify the object (that is why it is non-const)

I had a similar issue http://www.cplusplus.com/forum/general/40626/
I guess that the best bets will be template or const_cast

By the way, *& a_pBucket yuck.
The duplication is not a problem if it is just a small number of lines.

Can the the heavy lifting be separated out into one or two utility functions common to both?
Topic archived. No new replies allowed.