Correctness Qt - QList

A QList<T *> cannot 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 not do

 f(QList<T *>()); //Compile error 

more, since the compiler cannot discreetly discard QList<T *> until QList<const T *> . However, I can explicitly interpret QList as follows:

 template <typename T> inline QList<const T *> &constList(const QList<T *> &list) { return (QList<const T *> &)list; } 

This allows me to use the constList template constList to cast any QList<T *> to QList<const T *> , as in

 f(constList(QList<T *>())); 

and it seems to be working fine, but is it really safe?

+6
source share
2 answers

The casting function you are considering & hellip;

 template< class T > inline QList<T const*>& constList( QList<T*> const& list ) { return reinterpret_cast< QList<T const*>& >( const_cast< QList<T*>& >( list ) ); } 

& hellip; can be practical (perhaps QList does not change its representation of the object depending on the const -ness of the element type), but it can violate the correctness of const .

Firstly, since dropping the const -ness of the list itself does not match const : it allows you to change the original const list.

But even if this formal argument const removed, for example, & hellip;

 template< class T > inline QList<T const*>& constList( QList<T*>& list ) { return reinterpret_cast< QList<T const*>& >( list ); } 

& hellip; there is still a const correctness problem.

The reason is that the list is an additional level of indirection, and your function itself is not const . Thus, after using your function to get a link to a list with supposed const pointer elements, you can store a pointer to what const in this list. And then you can use the original list to change this const , bang element.

For the same reason that there is no implicit conversion from T** to T const** .

What you can do without such problems is that with the already specified const list of pointers to objects, they are forced to point to const objects:

 template< class T > inline QList<T const*> const& constList( QList<T*> const& list ) { return reinterpret_cast< QList<T const*> const& >( list ); } 

Formally, reinterpret_cast still exists as a potential problem, but any specialist who specializes in presenting QList on constness of elements seems to deserve what he received. :-)

Cheers and hth.,

+8
source

The idea of ​​correct construction is weak, and what you find is one of many reasons. The concept of Constess only captures one bit of semantics (change / does not change) and does it very poorly and at a rather high syntactic cost, which sometimes even requires code duplication.

One of the problems of this concept is that it does not scale very well in composition: for example, I would be interested in passing the function a const vector of non-constant objects or a non-constant vector of const objects or a const vector of const objects and getting syntax right is expensive ... just think about how standard C ++ was forced to introduce const_iterator , because this, of course, is different from const iterator .

Over the years, I moved from the position of fanaticism, using constant correctness in every place where, on the contrary, I could use it only where I was forced. Experience has taught me that code that is not obsessed with constant correctness becomes cleaner, and that the adversarial correctness system never catches (at least for me) any logical error, but only errors related to art itself. Unfortunately, const correctness is one of the things in C ++ that you are forced to use because C ++ rules talk about this, and there is no way to avoid using it.

I know that they will take me for this post, but my suggestion is to keep track of what you read about C ++ on this issue; hold your brain and judge objectively. Just because it would be nice if something were true (for example, that the correctness of the constants helps the programmer), unfortunately, this does not mean that this is really so.

No matter how big the name that signed the book.

Also remember that if a position requires the rest of the world to be wrong, then it is probably nice to be at least a little skeptical: most languages, even those born after C ++, do not implement this concept.

+2
source

Source: https://habr.com/ru/post/891382/


All Articles