Avoiding code duplicates in this particular case

Dec 12, 2011 at 1:14pm
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?
Dec 12, 2011 at 1:33pm
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));
}
Dec 12, 2011 at 1:38pm
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 Dec 12, 2011 at 1:42pm
Dec 12, 2011 at 2:04pm
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?
Dec 12, 2011 at 2:35pm
My understanding is that it is valid as long as the Bucket object is a non-const object.
Dec 12, 2011 at 2:44pm
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.

Dec 12, 2011 at 4:02pm
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.
Dec 12, 2011 at 4:14pm
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?
Dec 12, 2011 at 5:05pm
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 Dec 12, 2011 at 5:15pm
Dec 12, 2011 at 5:22pm
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 Dec 12, 2011 at 5:24pm
Dec 12, 2011 at 6:15pm
It would be better style to make this function return the value it produced rather than use the "out parameter".
Dec 12, 2011 at 6:26pm
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.
Dec 12, 2011 at 7:22pm
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.
Dec 12, 2011 at 9:01pm
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.
Dec 12, 2011 at 9:08pm
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.