I have a class Foo
which is in a self referencing tree-like structure (minimally):
class Foo {
public:
// Gets this child's position relative to it's parent.
int getPosition() const {
return parent->indexOf(this);
}
int indexOf(const Foo *const child) const {
return children.indexOf(child); // this line causes an error.
}
private:
Foo *parent;
QList<Foo *> children;
}
The line return children.indexOf(child)
expects const T &value
to be passed as per the QList docs, this resolves to Foo *const &value
for my scenario.
In order for my getPosition()
method to call my own indexOf()
method it is required to have a signature of const Foo *child
at minimum in order to pass this
from a const method. (Since this is const Foo *const
).
My code will not compile however as const Foo *const child
cannot be cast to Foo *const child
for QList::indexOf
. Neither of my methods modify the object state so they should be const (i.e. I don't want to un-cost getPosition
to receive a non-const this
).
So the question is, how do I go from this
in a const context (const Foo *const
) to what QList::indexOf
requires. Should I be const casting this
inside getPosition
since I know that my indexOf
(and subsequent calls) will not mutate it?
Is there something else I should have done? Perhaps my design is faulty.
As a common rule, it is very often considered a bad practice to use const_cast<>() in C++ code as it reveals (most of the time) a flaw in the design.
const_cast is one of the type casting operators. It is used to change the constant value of any object or we can say it is used to remove the constant nature of any object. const_cast can be used in programs that have any object with some constant value which need to be changed occasionally at some point.
The benefit of const correctness is that it prevents you from inadvertently modifying something you didn't expect would be modified.
The whole purpose of const is to prevent you from modifying something, that's why your code generates an error. Adding in const_cast is basically telling the compiler to shut up, that you know what you're doing.
I think this is a perfectly reasonable use case for const_cast
, however it's not this
you need to const_cast
, but child
. In this case, QList::indexOf
expects a constant pointer to a Foo
(Foo* const
) but child
is a constant pointer to a constant Foo
(const Foo* const
). There is no implicit conversion from Foo* const
to const Foo* const
because that would remove the const-ness from the value being pointed to.
So, to fix your code I would change the line to
return children.indexOf(const_cast<Foo*>(child));
You know QList::indexOf
is not going to modify whatever child
points to, so this won't produce undefined behavior. I would however add a comment explaining why the const_cast
is necessary.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With