views:

104

answers:

3

Consider a method like this:

void Parent::removeChild(Child *child)
{
    children.removeAll(child);
}

In this case, since child is never modified itself, one could make it a const pointer. But since children is of the type QList, the removeAll() takes a const reference to a non-const pointer.

What's the recommended way to handle this? Skip the constness of the method argument or to const_cast the const pointer to fit the removeAll() method?

A: 

If what you want is to say that changing the children list is not a change of a Parent instance, then just make the children list mutable.

However, make sure that it's really the semantic you want for you Parent class. If children are not part of the state of Parent (in your system's semantic), then it should be fine. If it is part of the Parent instance state, then you should keep a non-const member function.

The mutable keyword is there for thoses exceptional cases where a member of a class shouldn't be taken as the state of an instance, just additional informations. If it's your case then use it.

Otherwise let your member function be non-const as it modifiesa Parent member.

Klaim
`muatable` is about class members, not about function arguments. I highly doubt that the user is trying to make any function called `removeChild` `const`.
Billy ONeal
further to what @Billy said, `mutable` allows a `const` method to write non-`const` data. It *doesn't* allow a method which takes a `const T *` parameter to cast it to a `T *`.
Philip Potter
"then just make the children list mutable." It's the member I suggest to make mutable IF it's the wanted semantic.The fact is that the cast required here shows that Emil Eriksson don't want the Parent class to be considered "changed" if it's member `children` (the QList AFAIU) is changed. So to make his function const, he really need to make this list mutable OR assume that changing the list is really changing the Parent.Otherwise, const casting here is a patch that will only make things non-obvious for the class's users.
Klaim
A: 

Tricky one. You should have added some more code, but from the docs I assume that you have a QList<Child*> and cannot change it to a QList<const Child*> because you need to access the actual objects in a non-const manner.

Since all the removeAll() function does is to remove the entry in the list and it in no way modifies the pointed-to Child (how could it, it doesn't know anything about the Child class) it would be safe here to use a const_cast.

Martin
Now here's what I asked for :)
Emil Eriksson
A: 

It looks like QList is designed to be used on non-pointers. They define a lot of the interface that is const as const T& which would work great if your QList was on Child, not Child*.

It will work on pointers just fine, but it can't declare the constness right for them. I don't recommend changing your QList to Child unless it's cheap to copy, you have all the right semantics for copy ctor, dtor, op=, op==, etc and you don't mind having copies in the list rather than the objects you pass in. You can see how with int or strings, that it would work as expected (removeAll would be const correct).

If const correctness is important to you, then use a const_cast. Then declare a const ref and pass that in.

void Parent::removeChild(const Child *child)
{
    QList<Child*>::const_reference constRefToChild = const_cast<Child *> child;
    children.removeAll(constRefToChild);
}

The point of this is that if removeAll is ever changed to not take a const, you get a compiler error. Then you'd know that removeAll isn't preserving constness of the argument.

Lou Franco