A QList<T *>
can't easily be const-correct. Consider the function
void f(QList<T *> list)
{
list[0]->constFunction();
}
I can change f to
void f(QList<const T *> list)
but then I can't do
f(QList<T *>()); //Compile error
anymore, since the compiler can't implicitely cast QList<T *>
to QList<const T *>
. However, I can explicitely reinterpret-cast the QList as follows:
template <typename T> inline QList<const T *> &constList(const QList<T *> &list)
{
return (QList<const T *> &)list;
}
This enables me to use the constList
template function to cast any QList<T *>
into a QList<const T *>
, as in
f(constList(QList<T *>()));
and it seems to work fine, but is it actually safe to do this?
The casting function you're considering, …
template< class T >
inline QList<T const*>& constList( QList<T*> const& list )
{
return reinterpret_cast< QList<T const*>& >(
const_cast< QList<T*>& >( list )
);
}
… may be practical (probably QList
does not change its object representation depending on the const
-ness of the element type), but it can break const
correctness.
First, because casting away the const
-ness of the list itself is not const
correct: it allows you to change an originally const
list.
But even if that formal argument const
is removed, like …
template< class T >
inline QList<T const*>& constList( QList<T*>& list )
{
return reinterpret_cast< QList<T const*>& >(
list
);
}
… there is still a const
correctness problem.
The reason is that the list constitutes an additional level of indirection, and with your function is not itself const
. Thus, after using your function to get a reference to the list with alleged pointer-to-const
elements, you can store in that list a pointer to something that is really const
. And then you can use the original list to modify that really const
item, bang.
It's the same reason that there is no implicit conversion from T**
to T const**
.
What you can do without such problems is, with an already const
list of pointers to objects, make those pointed to objects const
:
template< class T >
inline QList<T const*> const& constList( QList<T*> const& list )
{
return reinterpret_cast< QList<T const*> const& >(
list
);
}
Formally there's still the reinterpret_cast
as a potential problem, but anyone specializating the representation of QList
on constness of elements would presumably deserve whatever they got. :-)
Cheers & hth.,
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