Comments

Why duplicates Qt so much of what is available in the STL (eg. Tulip containers such as QList, QVector, QStack, QQueue, etc.)? I don't see any reason to do this (that is not to say that there could be no reason, but I don't see the additional benefit).

Ever tried cross-platform development with STL? There are dozens of implementations all with their own bugs. On AIX for example, if you switch on large file support, the STL will suddenly live in std::LFS namespace instead of std. If you try to link an application that doesn't use LFS with a library that uses it, you'll get very interesting results.
Besides, Qt containers are more modern, use implicit sharing, feature java and stl iterators and are in most cases faster and more memory optimized. The other nice thing is that Qt doesn't force you to use its containers. If you insist using STL, all Qt containers have convenience constructors so you can pass a std::vector instead of a QVector.

"
Ever tried cross-platform development with STL? There are dozens of implementations all with their own bugs.
"
A technically superior approach would be to fix broken STL implementations instead of inventing an own set of containers. That is one point of standardization: To have a common set of components, so people do not need to invent their own. To this end, the decision of Trolltech is really a bad one. Of course I realize that just having a set of containers on every platform supported by Qt is not the only reason for "Tulip". I guess features like implicit sharing or other additional features over the STL are just as well a reason. That Trolltech is able to deliver performance tuned components is nice to have too.

It is sad however to have to read statements like this in Trolltechs documentation: "The containers provide new iterators with a nicer, less error-prone syntax than STL, inspired by Java's iterators."
Such bogus FUD from them just hurts.

The unix vendors created Motif to have a common set of graphical components, so people do not need to invent their own. By this logic a technically superior approach to Qt would be to fix broken Motif implementations instead of inventing another set of widgets.

Tulip's containers provide new iterators with a nicer, less error-prone syntax than STL, and they are inspired by Java's iterators. This is neither bogus nor FUD.

"
The unix vendors created Motif to have a common set of graphical components, so people do not need to invent their own. By this logic a technically superior approach to Qt would be to fix broken Motif implementations instead of inventing another set of widgets.
"
I explicitly said that I realize that Qt needs additional features over those provided by the STL. And on such grounds I do not criticize Trolltech. I just said that the solution to non-compliant STL implementations are compliant STL implementations and not another set of containers.

By the way (this is not really on topic), the example with Motif shows the value of a *real* standard (as C++ is) versus a loose agreement of vendors (in this case to provide some common software component).

"
Tulip's containers provide new iterators with a nicer, less error-prone syntax than STL, and they are inspired by Java's iterators. This is neither bogus nor FUD.
"
The claim that these iterators are less error-prone is entirely unsubstantiated by Trolltech. So Trolltech scares people that not sticking with STL-style iterators will make their code worse. The notion that you have to use the software of one specific vendor, or you will suffer, without any evidence shown is FUD by my understanding. What do you think?

Do not get me wrong though, in general I think Qt is a very good toolkit. In general, Qt "just works". It is just that I prefer the C++ equivalents where functionality of C++ and Qt overlaps, and I would recommend this practice to others as well, for the sake of interoperability.

"The claim that these iterators are less error-prone is entirely unsubstantiated by Trolltech. So Trolltech scares people that not sticking with STL-style iterators will make their code worse. The notion that you have to use the software of one specific vendor, or you will suffer, without any evidence shown is FUD by my understanding. What do you think?"

Java-style iterators are less error-prone in different ways. With STL-syntax it is easy to accidentally dereference the end element, and it's difficult to filter out certain elements (you need to increment manually, but only if you didn't remove an element). That kind of code simply doesn't look nice, Java solved it by having iterators between the elements rather than having pointers to elements. But what's worse is that STL iterators don't work well with implicitely shared classes, and all of Qt's container classes are implicitely shared. If you start iterating with begin() and while you are in the loop some function makes an implicitely shared copy of the container, you first might end up modifying both copies, and then your program crashes because the next call to end() detaches container, so your iterator never reaches end().

If you make a copy of the container, and changing the copy also does something to the original (other than decrease a refcount) then there is something very very wrong with your container.

You can quickly get in to trouble if you modify an STL container while you are iterating though it, but fortunately it's easy enough to iterate through a copy of the container (and normally this is good enough).

> If you make a copy of the container, and changing the copy also does something to the original (other than decrease a refcount) then there is something very very wrong with your container

Sorry, you didn't understand. In the scenario describe changing the *original* changed the copy, not the other way round. There's nothing wrong with the container, but with the concept of STL iterators.

Let me try to explain it differently:

First understand implicit sharing, and then look again at the STL iterator pattern. An STL iterator is essentially a pointer into the container's data structure. They are used under the assumption that they are as lightweight as pointers and can be assigned and copied without any overhead. That's the beauty of the STL: an iterator behaves like a pointer to a pointer, semantically and performance wise. If you changed this, code using STL iterators would become horribly slow.

Fixing the mentioned problem is only possible if you make STL iterators aware of the container they are iterating over, and make the container keep track of the number of instances of iterators on it. Qt could do this, but then you would want to use the STL iterators even less with it (because it would be slow).

The other alternative is to make any call that returns a STL iterator (like begin() and end()) turn off sharing for good. That's even worse.

Face it, the STL is not about implicit sharing. That's why Java-style iterators are safer.

"
Sorry, you didn't understand. In the scenario describe changing the *original* changed the copy, not the other way round. There's nothing wrong with the container, but with the concept of STL iterators.
"
Either you provide containers with correct copy semantics or you do not and disallow copying, or at least document that copy is destructive. But then your iterators are not really STL compatible (you can still use some STL algorithms however). The GNU libstdc++ std::string implementation is reference counted and it does not suffer from strange copy semantics (*).

"
Fixing the mentioned problem is only possible if you make STL iterators aware of the container they are iterating over, and make the container keep track of the number of instances of iterators on it. Qt could do this, but then you would want to use the STL iterators even less with it (because it would be slow).
"
That is one of multiple possible ways. But this affects only the implementation of the iterators, not their style of usage.

"
Face it, the STL is not about implicit sharing. ...
"
Very true.

"
... That's why Java-style iterators are safer.
"
If you make STL-style iterators sufficiently "dumb", of course you can easily show that Java-style ones are safer. Turn on library debug mode with newer GCC versions and you get quite safe STL iterators.

(*) This reference counted implementation is not without problems too. For example some methods might throw which can give the guarantee to not throw in other implementations. And there are issues with multi-threading of course.

"
With STL-syntax it is easy to accidentally dereference the end element, and it's difficult to filter out certain elements (you need to increment manually, but only if you didn't remove an element).
"

But that can be solved with wrapper functions, you do not need another iterator style for it.

And Java-style iterators have weak points too. For example iterators which belong only to the InputIterator category: The "hasNext" operation is difficult if not impossible to implement for them. Because by the time of calling hasNext, you do not even really know if extracting one more element from the input will succeed or fail.
And I imagine that as soon as you have multipass algorithms, the notation that at no point in time a Java-style iterator points at a valid element, and that value retrieval and incrementation are one tied together operation, can bring confusion and thereby problems too.

That the considerably lower flexibility of these Java-style iterators can not fully support building frameworks like the STL is also detrimental to software quality in tendency.

So while Java-style iterators allowe for a nicer coding style for some purposes, I still fail to see a reason why the should be unanimously called less error prone.

But all in all, as they are optional, I guess STL- versus Java-style will not be such a big deal anyways. Lets see how things develop.

>It is just that I prefer the C++ equivalents where functionality of C++ and Qt overlaps, and I would recommend
>this practice to others as well, for the sake of interoperability.

I would go the other way and recommend using the Qt version of the functionality, for the sake of portability. Since you will use the same implementation on all targets, and not having to deal with vendor and implementation specific differences.

"
I would go the other way and recommend using the Qt version of the functionality, for the sake of portability. Since you will use the same implementation on all targets, and not having to deal with vendor and implementation specific differences.
"
Just in case you did not mean to make a joke, I can detail you why that suggestion would be nonsensical.

This was not meant as a joke, so please enlighten me why it is nonsense to use the Qt versions of functionality? Take the case of using the Qt versions instead of STL functionality, I could happily use the same code on Windows, Mac, Linux'es, Solaris, AIX and HP-UX without having to deal with different implementations of STL on the different platforms. In my book that's a big win in portability and the biggest reason one uses cross platform toolkits.

Think what would happen if it is indeed recommended to use Qt and not the STL, and people would actually use it in masses. Then the market for Qt-API compatible libraries would be so great that competitors would step up. These competing libraries would of course have the same subtle differences from the origin as today there are with different STL implementations. So you have gained nothing, you would still have to care for different implementations.

[ Besides, to only have to cope with one implementation one could also recommend to just use Stlport for example. ]

That is irrelevant, I recommend using the Qt versions when you already uses the Qt libs not replacing STL with the Qt version when no other part of Qt are needed. Then your competing library's have to compete with the whole Qt not some small part. And this would not destroy any standards, only make Qt one.

One could do as you say and use Stlport, but you don't gain anything just create an somewhat unnecessary dependency on a 3rd party lib. There are a few reasons not to use the Qt versions of functionality, but they are mostly technical reasons. Things like performance and resource usage, or if the other solution are easier and less eror prone to write. Or if you, or the team are very experienced using the non Qt functionality. Like being able to write STL code blindfolded and knowing of all the pitfalls of the different implementations. Then it makes sense to not use Qt, all other resons are of category education, philosophy, religion or masturbation.

"
That is irrelevant, I recommend using the Qt versions when you already uses the Qt libs not replacing STL with the Qt version when no other part of Qt are needed.
"
Really?

This was your original Posting (the quote is part of mine):
-------------------------------
>It is just that I prefer the C++ equivalents where functionality of C++ and >Qt overlaps, and I would recommend
>this practice to others as well, for the sake of interoperability.

I would go the other way and recommend using the Qt version of the functionality, for the sake of portability. Since you will use the same implementation on all targets, and not having to deal with vendor and implementation specific differences.
------------------------------------

So, you were indeed talking about replacing STL usage by Qt usage in overlapping functionality.

"
One could do as you say and use Stlport, but you don't gain anything just create an somewhat unnecessary dependency on a 3rd party lib.
"
You gain exactly what you were talking about: "... you will use the same implementation on all all targets, and not having to deal with vendor and implementation specific differences."

Yes, that's rather implicit since the whole thread are about Qt in the first place. If you are not using Qt, any functionality it provides is a totally unrelated matter. And there are no overlaps since it's not a part of the equation. It would be rather silly to recommend usage of a GUI bound library when none is needed or another one already is in use.

As much as I hate to dive into this rather heated dicussion, it has long been planned that Qt4 will be shipped as a couple of complimentary libraries, one of which "Qt Non-Visual" provides containers, file access primitives etc. without any GUI code or dependencies.

This means it could become an alternative to the STL for programming in C++. Personally I like that idea. I find the Qt syntax easier to learn and read, but as I've done most of my programming in Java and Delphi, I have an obvious bias.

Yes, that's rather implicit since the whole thread are about Qt in the first place. If you are not using Qt, any functionality it provides is a totally unrelated matter.
"
Then we were not talking about the same matter; I do not see myself at fault here, since I clearly stated that I was talking about overlapping functionality. You replied to that statement.

"A technically superior approach would be to fix broken STL implementations instead of inventing an own set of containers. That is one point of standardization: To have a common set of components, so people do not need to invent their own."

Although true, it's not as if Trolltech has access to the source code of the STL on every supported platform. I have found Qt's container classes to be invaluable in the development of kfile_torrent, as many people had problems linking my STL code due to weird differences in the std namespace.

"It is sad however to have to read statements like this in Trolltechs documentation: 'The containers provide new iterators with a nicer, less error-prone syntax than STL, inspired by Java's iterators.' Such bogus FUD from them just hurts."

It's not FUD, and it's not bogus. Although the STL iterator mechanism is certainly more generic, it has more opportunities for typos and other annoying programmer errors.

There are more references to "it" in the STL method, and you have to make sure you increment the iterator yourself (in this case done in the for loop, but lots of people forget this when doing while loops), which is done automatically with Java-style iterators. One thing that is really annoying about STL-style iterators is removing elements from the container you're iterating over.

Now, this is coming from someone who is as big a believer in C++'s strengths over Java as anyone, but it's clear to me that although Java iterators are less generic (and thus harder to use when doing weird things), they're more appropriate than STL-style for 95% of the things a programmer needs to do.

> But this is just the special case where you are iterating over a whole
> container.

iterating over the whole container or just a part of it, the same loops generally occur. there are some cool STL algos that do cover certain cases better than iterating in a for or while loop, but the for or while loop iteration is the common case, not a "special case" at all.

> What do you do with arbitrary ranges? These are not even supported by such
> Java-style iterators.

i believe that was the 5% Michael was alluding to. use the right tool for the right job. we now have both sorts of iterators to utilize. hooray!

but look through KDE's code base sometime and see how often the Java-style iterators would be an improvement versus when they wouldn't. personally, i think a 95% success rate is a bit on the conservative side =)

"
i believe that was the 5% Michael was alluding to. use the right tool for the right job. we now have both sorts of iterators to utilize. hooray!

but look through KDE's code base sometime and see how often the Java-style iterators would be an improvement versus when they wouldn't. personally, i think a 95% success rate is a bit on the conservative side =)
"
Ahh, okay, I guess I have to admit, having two styles as an option is better than having only one.

It is just that the claim I cited (and the availability of Qts containers) should not make people believe that abandoning the STL in general would be good thing. Just think what would happen if every John Schmoe project would invent its own style of containers and algorithms. A nightmare in my opinion.

The fact that you're not using a generic default keyword and instead aliasing each item with the word painting leads to self documenting code. Instead of getting off on "computer science"-ese and bothering with iterators, this is more natural, at the very least to those familiar with English or languages with remotely similar grammar.

Right? lambda is basically declaring an anonymous function. If it confuses you: s/lambda/function/

So, again, I don't see what the advantage of Ruby's bastardized syntax is at all. It seems to me that Ruby proponents don't really know what the syntax is derived from (you talk about iterators and self-documenting code and all that), whereas functional language people look at Ruby and see a bastardized syntax with no explanation as to why.

Functional languages are as much "computer science"-ese as anything else. So I don't know about that high horse of yours. :-)

Lambda doesn't do much. It does not tell me the purpose of the SOLUTION, it's superfluous -- it does however tell me, in gory if not "Captain Obvious" style detail, the means of the solution, but that's uninteresting in every case that Ruby attempts to address. One might think it to be necessary, but languages are a tool for expression of solutions for a domain of problems, their study and methods of construction are an another matter, lambda belongs in the latter. It does nothing when one says that it's an anonymous function. I suggest some study of pragmatics, it should be very obvious why "|alias|" was used. It's not bastardized syntax.

The world is moving towards targeted languages, in particular domain specifics are highlighted while the rest is kept to a minimum or not at all via inference. Such generic concepts (lambda) are best kept in their domain. Rightly so, I might add. It makes little sense to spew "computer science"-ese when we're talking about an e-store or accounting software or what have you. It makes sense to speak in the terminology of the domain. Not to mention the fact that it is elementary to the language and thusly and user would know what it means by spending a few minutes with the tutorial, that's quite a bit less start-up cost than learning computing science from the ground up as one would require in your model. Now I concede Ruby isn't addressing the space of meta-programming, but it does outline a rough domain which it attempts to address and does so surprisingly well.

Upon consideration of your remarks about functional languages, it seems your comments betray a lack of experience with Lisp. I thought you would know that, typically, the approach is to build DSLs or syntactic sugar and other abstractions to move away from the base language.

Wow man. Your lecture does nothing for me, but wow. I applaud your simultaneous display and denial of hubris.

I can't believe you really wrote all that. The differences between the lambda syntax and the almost-uglier {||} syntax are in reality *so* trivial, I honestly fail to see how you can write so many words in defense of the latter. Replace "lambda" with "bind" and don't you get the same thing in appearance?

Any programmer would look at that {||} and they would want to know how it worked, what it was doing, and how to do the same thing in their own code. Eventually they would find out about "yield" and "co-functions" and then they would realize how much uglier and inelegant the whole thing is compared to the powerful concept it's based on.

And wow, attacking me for lack of knowledge in Lisp. Nice one.

I guess you Ruby people have something in common with us Gentoo people. We're freaks who're unable to see that we're freaks. :-)

"Ruby people" are usually fairly congenial (if the mailing list is any indication). However, when you come up and lambast someone's pet language for having "bastardized syntax" and so on, what exactly do you expect to happen?

Do you even know Ruby beyond the one-line snippet that was posted above?

I've been waiting for Qt4's Scribe because KOffice development has slowed while waiting for it (Kword works great, I use it, but it hasn't been updated in awhile and picture layout still has some bugs).

Once you build it try out the arthur example... Stunning.
Double buffering built in to all QWidgets, AA edges, alpha built into QColor.. It rocks.

Designer shocked me with the new GIMP-like interface. You can get used to it, but i'm not too impressed. What did impress me in designer is the visual connecting of signals and slots (screenie attatched).