Alternatives to the C++ Standard Library?

S

Steven T. Hatton

Now that I have a better grasp of the scope and capabilities of the C++
Standard Library, I understand that products such as Qt actually provide
much of the same functionality through their own libraries. I'm not sure
if that's a good thing or not. AFAIK, most of Qt is compatable with the
Standard Library. That is, QLT can interoperate with STL, and you can
convert back and forth between std::string and Qt::QString, etc.

Are there any other libraries based on Standard C++, but not on the C++
Standard Library? What might these be? Why do people create these? Are
any significantly different from the C++ Standard Library? Is it good that
people create their own basic libraries instead of using the Standard
Library?
 
D

Donovan Rebbechi

Now that I have a better grasp of the scope and capabilities of the C++
Standard Library, I understand that products such as Qt actually provide
much of the same functionality through their own libraries. I'm not sure
if that's a good thing or not.

For the most part, it's not a very good thing, and if one were building these
toolkits from scratch today, they would be done differently (one would hope...)

Many of these toolkits predate the C++ '98 standard. So they built
similar infrastructure (actually, usually worse. Most pre-STL container
toolkits look pretty amateurish compared to STL)

One of the benefits of using a mature language is that there are all of these
toolkits to work with. But part of the price you pay is that there is a lot
of baggage as well -- you get things that are written to old standards, and
then have to be bent and twisted to work with new standards. There are
examples of this in the C++ language itself.
AFAIK, most of Qt is compatable with the
Standard Library. That is, QLT can interoperate with STL, and you can
convert back and forth between std::string and Qt::QString, etc.

Are there any other libraries based on Standard C++,

Qt is not really based on standard C++, since it predates that (the Qt
project started around 1996 or so)

So you could go and implement your new and improved toolkit that's integrated
with STL, or settle for the mature one that is awkward to use with STL. Or
you could look for a toolkit written by someone else post-standard that is
more STL friendly (but probably less mature than the pre-standard kits).
Choose your poison.

Cheers,
 
J

John Carson

Steven T. Hatton said:
Now that I have a better grasp of the scope and capabilities of the
C++ Standard Library, I understand that products such as Qt actually
provide much of the same functionality through their own libraries.
I'm not sure if that's a good thing or not. AFAIK, most of Qt is
compatable with the Standard Library. That is, QLT can interoperate
with STL, and you can convert back and forth between std::string and
Qt::QString, etc.

Are there any other libraries based on Standard C++, but not on the
C++ Standard Library? What might these be? Why do people create
these? Are any significantly different from the C++ Standard
Library? Is it good that people create their own basic libraries
instead of using the Standard Library?

I think you will find that most of the libraries pre-date the standard
library (i.e., they date from pre-1998). MFC, which, like QT, pre-dates
standard C++ by many years, has its own string, array, list and map classes,
as does ATL (Active Template Library).

These classes linger on because of backward compatibility, because
programmers are familiar with them and don't want to change, and (sometimes)
because they embody different design decisions that are genuinely preferable
for some purposes.
 
S

Steven T. Hatton

Donovan said:
For the most part, it's not a very good thing, and if one were building
these toolkits from scratch today, they would be done differently (one
would hope...)

I've been using Qt based products since 1997 when the KDE was still in
alpha. I don't believe Trolltech have significant misgivings about the
core design of their libraries, and since they reinvent the blinkin' thing
about once every two years, whatever they would have done differently, has
been done differently.
Many of these toolkits predate the C++ '98 standard. So they built
similar infrastructure (actually, usually worse. Most pre-STL container
toolkits look pretty amateurish compared to STL)

I don't belive the QTL will fit that category. The functionality offered in
their API is arguably superior to that of the Standard, and the Standard
doesn't specify implementation.
One of the benefits of using a mature language is that there are all of
these toolkits to work with. But part of the price you pay is that there
is a lot of baggage as well -- you get things that are written to old
standards, and then have to be bent and twisted to work with new
standards. There are examples of this in the C++ language itself.

I've seen this happen with Java and Qt. The first release was dramatically
altered in the next major version. This broke a lot of the original
software. Fortunately for the Qt and Java developers, that break with the
past was worth the improved functionality. As Java and Qt became more
established, there was more concern with backward compatability. I have to
give Trolltech credit for their audacity in rolling out a major redesign in
Qt4 while including a full backward compatability subset.
Qt is not really based on standard C++, since it predates that (the Qt
project started around 1996 or so)

I disagree. There really is nothing in Qt that is not implemented using
Standard C++. Basically what they do is provide some language extensions
which are processed by the MOC to produce pure, Standard C++. I don't like
the amount of #MACRO magic they use, but the only times I've really had
problems with it are when I have collisions with Boost #MACRO magic. Since
boost is pretty much the playground of the Standard Committee, it's hard to
be too critical of Trolltech in that situation.
So you could go and implement your new and improved toolkit that's
integrated with STL, or settle for the mature one that is awkward to use
with STL. Or you could look for a toolkit written by someone else
post-standard that is more STL friendly (but probably less mature than the
pre-standard kits). Choose your poison.

Actually, the QTL containers are, AFAIK, fully compatable with STL
algorithms, and there is no reason that I can think of for not being able
to construct STL from QTL containers and vis-verse. The QTL containers
offer additional features such as implicit sharing, and "Java-style"
iterators. Hopefully, C++0X will adopt the new for() semantics supporting
forEach functionality. That will make Qt's current foreach #MACRO
redundant. For now, Qt offers that additional, and superior functionality.

As for QString verses std::string, the advantage std::string has is that
it's standard. Beyond that, I don't believe it even comes close to
QString, and that doesn't even address QStringList.

The downside I see with using QTL is that it is bound to Qt. As you might
have gathered, I'm a big fan of Qt. Nonetheless, I want my code to stand
on its own in areas where it should be toolkit agnostic.
 
D

Dietmar Kuehl

Steven said:
Is it good
that people create their own basic libraries instead of using the Standard
Library?

C++ is very much about the freedom to do thing the way you want to
do them. If you don't like a feature, you would not use it but you
would use something different. Essentially, C++ is intended to
provide the infrastructure to create your own library and it tries
to get out of your way as much as possible. There are a few aspects
which are technically in the standard library which you can't avoid
entirely like operators new and delete (although you can even replace
these if you really want to), the RTTI stuff, or the basic exception
types thrown by language constructs (e.g. bad_cast) but most of the
stuff you can choose from alternatives.

Personally, I think this is the right way to go for a language: it
provides facilities which are reasonable to use (and actually superior
in many cases to alternatives although not always) and allow you to do
real work. However, providing the possibility to use alternatives
opens the door for new inventions. Actually, the intention behind the
relatively minimalist standard library in C++ is to open a market for
people providing advanced features as is done by several vendors or
organizations (for example, Qt, Tools++, Boost; see the Available C++
Libraries FAQ for a more complete list).

That said, I want to point out that the standardization committee did
something quite remarkable when they put together the standard C++
library: in an environment buzzing about object-orientation, they
realized that object-orientation is the wrong approach to many of the
real task in programming! Instead, all algorithmic work is better done
in a rather different form using other mechanisms than classes and
virtual functions. The result was the introduction of STL into the
standard C++ library (of course, the major credit for the creation of
STL and the theory behind it goes to Alexander Stepanov and David
Musser but the C++ committee had the courage to bring their avantgarde
product forward as part of the standard). Everybody creating a new
library is well-advised to understand why STL works that well and to
built on this experience! Of course, STL is not ideal (in fact, I have
a major problem with the basis STL is built upon: the iterator concept
should have been split into two distinct concepts, i.e. cursors and
property maps) but the approach taken (using techniques which now go
under the name "generic programming") is right on target.
 
C

Calum Grant

Steven said:
Now that I have a better grasp of the scope and capabilities of the C++
Standard Library, I understand that products such as Qt actually provide
much of the same functionality through their own libraries. I'm not sure
if that's a good thing or not. AFAIK, most of Qt is compatable with the
Standard Library. That is, QLT can interoperate with STL, and you can
convert back and forth between std::string and Qt::QString, etc.

Are there any other libraries based on Standard C++, but not on the C++
Standard Library? What might these be? Why do people create these? Are
any significantly different from the C++ Standard Library? Is it good that
people create their own basic libraries instead of using the Standard
Library?

The Boost libraries are designed to work as closely with the STL as
possible. This means that they essentially build on and enhance the
STL, rather than duplicating its functionality.

Wherever possible, the "standard" way should be used (i.e. the STL), since
- code is more portable
- the STL is generally more efficient
- the STL is generally better debugged than home-brew implementations
- it will integrate better with other libraries, and STL functions and
algorithms
- All C++ programmers will understand such code (and if they don't they
can't really be called C++ programmers).
- there is less conversion back and forth between different formats
(e.g. QString, char*, BSTR, std::string, CString) so it is more
efficient to use just one string type.
- your code has fewer dependencies; it can assume the STL will always be
available.

Generally, non-STL libraries were written before compilers had decent
template support. Also, some C++ programmers are still a little uneasy
about templates. Some libraries/wizards require the use of idioms like
BSTR and CString, this is a real nuisance.

Calum
 
P

Panjandrum

Steven said:
Now that I have a better grasp of the scope and capabilities of the C++
Standard Library, I understand that products such as Qt actually provide
much of the same functionality through their own libraries.

The STL zealots will beat you ...
I'm not sure
if that's a good thing or not. AFAIK, most of Qt is compatable with the
Standard Library. That is, QLT can interoperate with STL, and you can
convert back and forth between std::string and Qt::QString, etc.

Are there any other libraries based on Standard C++, but not on the C++
Standard Library? What might these be? Why do people create these? Are
any significantly different from the C++ Standard Library? Is it good that
people create their own basic libraries instead of using the Standard
Library?

Unfortunately, there isn't much (STL based or not),e.g.:
http://www.ncbi.nlm.nih.gov/books/bv.fcgi?call=bv.View..ShowTOC&rid=toolkit.TOC&depth=2
http://www.gnu.org/software/commoncpp/
http://seal.web.cern.ch/seal/
http://synesis.com.au/software/stlsoft/
http://www.cs.berkeley.edu/~smcpeak/elkhound/sources/smbase/
 
P

Panjandrum

Calum said:
The Boost libraries are designed to work as closely with the STL as
possible. This means that they essentially build on and enhance the
STL, rather than duplicating its functionality.

Wherever possible, the "standard" way should be used (i.e. the STL), since

Whenever possible the KISS way should be used and not the STL/Boost
MICI (make it complicated and impenetrable) way.
 
S

Steven T. Hatton

Dietmar said:
C++ is very much about the freedom to do thing the way you want to
do them. If you don't like a feature, you would not use it but you
would use something different. Essentially, C++ is intended to
provide the infrastructure to create your own library and it tries
to get out of your way as much as possible.

I'm very much a believer in standardization where it is appropriate. IOW,
there should not be several different "flavors" of C++ available which, at
their core, result in non-portable code. When there is a reasonably good
open standard, I believe its best to adopt it, rather than use something
that will not work with programs that do adhere to the standard. This is
the strength behind the Internet, and a significant accomplishment of the
IETF.

[...]
Personally, I think this is the right way to go for a language: it
provides facilities which are reasonable to use (and actually superior
in many cases to alternatives although not always) and allow you to do
real work. However, providing the possibility to use alternatives
opens the door for new inventions. Actually, the intention behind the
relatively minimalist standard library in C++ is to open a market for
people providing advanced features as is done by several vendors or
organizations (for example, Qt, Tools++, Boost; see the Available C++
Libraries FAQ for a more complete list).

I agree that the Standard Library does a pretty good job of this. It's kind
of hard to know what else might be worth adding. People talk about basic
support for threading, and Stroustrup wants a GUI abstraction library.
Something I call an AUI (Abstract User Interface). The biggest problem I
see in adding such elements is that they could lead to restrictions on the
kinds of solutions people feel they should build. If the Standard supports
on threading model, and someone else comes up with something superior, the
superior solution might be rejected because it is seen as "non-standard".
OTOH, it's nice to have some accepted standard way of doing these things.
That said, I want to point out that the standardization committee did
something quite remarkable when they put together the standard C++
library: in an environment buzzing about object-orientation, they
realized that object-orientation is the wrong approach to many of the
real task in programming! Instead, all algorithmic work is better done
in a rather different form using other mechanisms than classes and
virtual functions.

Don't tell anybody, but the mem_fun stuff uses pointer to member which is,
as I understand it, one of the more expensive virtual operations. That may
all get optimized away. I really don't know.
The result was the introduction of STL into the
standard C++ library (of course, the major credit for the creation of
STL and the theory behind it goes to Alexander Stepanov and David
Musser but the C++ committee had the courage to bring their avantgarde
product forward as part of the standard). Everybody creating a new
library is well-advised to understand why STL works that well and to
built on this experience!

Actually, from what I recently read, some of the credit goes back to
Stroustrup for introducing the concept of parameterized types in the first
place. I've recently come to realize the Standard Library is not really as
complicated, and intractable as it once seemed to me. There are basically
two different kinds of primary entities, containers, and namespace local
functions that operate one them. A third category is probably worth
identifying in the function operators. That category is probably best
understood in terms of two subcategories. The actual function object
classes, and the funcitons that use (or create) them. It seems a shame
strings and I/O are treated, more or less, as distinct facilities, when in
principle, they could be treated in a way that would be more congruent with
the STL.
Of course, STL is not ideal (in fact, I have
a major problem with the basis STL is built upon: the iterator concept
should have been split into two distinct concepts, i.e. cursors and
property maps) but the approach taken (using techniques which now go
under the name "generic programming") is right on target.

Interesting. When I think of property maps, I think of key/value pairs. Is
this the kind of concept you are envisioning?

I'd be happy just to see std::vector<int> v; v::iterator it = v.begin(); Do
you know if that is in the works?
 
S

Steven T. Hatton

Panjandrum said:
Whenever possible the KISS way should be used and not the STL/Boost
MICI (make it complicated and impenetrable) way.

Are you confusing "complex" with 'arcane'? The STL is really very simple.
It just doesn't present a very intuitive interface. For example, this is
not all that compicated:

template<class ForwardIterator1,
class ForwardIterator2,
class BinaryPredicate>
ForwardIterator1 search(ForwardIterator1 first1, ForwardIterator1 last1,
ForwardIterator2 first2, ForwardIterator2 last2,
BinaryPredicate pred);

But without a bit of additional knowledge, it doesn't make a lot of sense.

Likewise for this example from TC++SL (stripped of comments):

transform (coll1.begin(), coll1.end(),
back_inserter(coll2),
bind2nd(multiplies<int>(),10));

The notation simply does not speak clearly for itself. You have to
understand what is happening with each parameter, and what it means. The
function object stuff can be especially hard to sort out.

bind2nd(multiplies<int>(),10))

actually means (_ * 10), where _ is the element from the container being
iterated over.

Boost is a mixed bag. Some of the stuff is very clear, powerful, and
useful. The Boost.Signals library looks pretty clear and usable. The
basics of Boost.Lambda also look easy to use. But Boost.Lambda looks to me
like the introduction of a completely new (functional) language, and could
be very hard to learn. It might also be very powerful once you do learn
it.

Though it's a core language feature, this, to me, looks like the essence of
C++ thinking, and makes me wonder why C++ is the follower in introducing
the construct (assuming the good idea is approved):
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1796.html
 
D

Dietmar Kuehl

Steven said:
I'm very much a believer in standardization where it is appropriate. IOW,
there should not be several different "flavors" of C++ available which, at
their core, result in non-portable code.

This is not what I was saying, though. C++ tries to provide a portable
core on which to build libraries. Whether these take advantage of the
standard library facilities or not is up to these libraries.

Of course, currently, the standard C++ library does not address some
areas at all and libraries have to create them using non-portable
facilities. Important areas include GUIs, sockets, and multi-threading
(see below for multi-threading, however). This should be addressed in
some form although I'm not aware of any proposals for GUIs or sockets
and the timeline essentially dictates that no new proposals for C++0x
are accepted after the next committee meeting (in October). Actually,
some people favored the idea of not accepting any new proposals at all
at the last meeting (i.e. if somebody wants to propose something really
important, better hurry and create a proposal...).
When there is a reasonably good
open standard, I believe its best to adopt it, rather than use something
that will not work with programs that do adhere to the standard.

Interoperability and portability are two different things. It may well
be reasonable to create own libraries and use these within a community
rather than using what the rest of world uses. In fact, there are
clearly several rather different styles of programmin C++ anyway. The
"MFC style" and the "STL style" are rather different approaches. Also,
some people will disagree with my assessment that the generic approach
is the way to go and prefer an object oriented approach. It is a free
world and everybody is entitled to seek his luck where he thinks he'll
find it - they'd just better not complain to me about seeking it in
object orientation and not finding it there because I told them :)
This is
the strength behind the Internet, and a significant accomplishment of the
IETF.

You'll find that something things work together and others don't even
in this area. It is generally quite reasonable to use different
approaches to solve different problems.
I agree that the Standard Library does a pretty good job of this.

You mean in opening a market for other libraries?
It's kind of hard to know what else might be worth adding.

Contenders are clearly things which can't be done portably right now.
People talk about basic
support for threading, and Stroustrup wants a GUI abstraction library.
Something I call an AUI (Abstract User Interface). The biggest problem I
see in adding such elements is that they could lead to restrictions on the
kinds of solutions people feel they should build.

Correct. ... and there are different movements within the standardization
committee or groups which work on proposals. My personal view is to do
a minimalist job and create the bare minimum which is needed to avoid
platform specific code and let others build portable libraries on these
basis. Other have different ideas, though.
If the Standard
supports on threading model, and someone else comes up with something
superior, the superior solution might be rejected because it is seen as
"non-standard". OTOH, it's nice to have some accepted standard way of
doing these things.

Especially with respect to threading, it is generally accepted that it
cannot be done by a library alone. The compiler also has to make certain
guarantees about reordering of statements. I think that the direction
championed by Andrei Alexandrescu and Hans Boehm which builds upon ideas
from the "lock free multi-threading" community is the right way to go
but I have no idea whether this is too avantgarde - I hope it is not.
.... but then, the C++ committee got hurt at the leading edge before
(although STL is a huge success, there were also many problems introduced
by standardizing features nobody had experience with; although this does
not that badly apply to STL itself but it clearly applies to features
which were necessary to make STL work).
Don't tell anybody, but the mem_fun stuff uses pointer to member which is,
as I understand it, one of the more expensive virtual operations. That
may all get optimized away. I really don't know.

STL is mostly about interoperability. Thus it is only consistent to
provide facilities which allow interoperability with object oriented
features. In fact, generic programming is not about replacing object
oriented techniques but it is a complementary technique which is good
at things where object orientation is bad at (although some highly
religious object orientation believers will consider the indication
that object orientation is not the panacea as blasphemy - I don't mind
since I intend to go to object orientation hell, i.e. to generic
programming heaven :)
Actually, from what I recently read, some of the credit goes back to
Stroustrup for introducing the concept of parameterized types in the first
place.

Yes and no. The basics concepts of generic programming where developed
entirely independent of C++ and were tried in languages like Ada and
Scheme before. The credit of Stroustrup with respect to generic
programming was to create the basis of the template mechanism we now
have and to explain this (together with Andrew Koenig if I remember
correctly) to Alexander Stepanov who realized that C++ provides the
model he was looking for.
I've recently come to realize the Standard Library is not really
as complicated, and intractable as it once seemed to me.

It is not complicated at all. It is actually quite simple. There is
just one thing to realize: the core of STL are concepts - not more
but no less. The rest is quite irrelevant to the understanding of
STL although it is the stuff which make it useful.
There are basically
two different kinds of primary entities, containers, and namespace local
functions that operate one them.

Apparently, you haven't understood what STL is about ;-) There are just
a few kind of entities which are completely described by concepts with
the central concept (group) being the iterators. Actually, STL
essentially revolves around iterators: they are used by the algorithms
and provided by the containers which decouples the algorithms from the
containers and allows independent realization of algorithms and
containers. BTW, containers are entirely irrelevant to STL. STL
operates on sequences, not containers. There is a huge conceptual
difference between these two.
Interesting. When I think of property maps, I think of key/value pairs.
Is this the kind of concept you are envisioning?

Yes, this is essentially it: cursors provide a position and some form
of a "key" and a property map provides values associated with the "key".
However, the "key" can be just an index into a vector or a reference to
the value itself. How the property map accesses a value related to a
key is entirely up to the property map. In particular, you should rather
envision an index lookup than a lookup in map or a has, i.e. the
property map access should be considered to be a cheap O(1) access
although it may be more involved.
I'd be happy just to see std::vector<int> v; v::iterator it = v.begin();
Do you know if that is in the works?

I don't think it is but I'm not sure. I'd consider it more important
to work on some form of lambda expressions because this would remove
the need to name these types in the first place! The above looks
cunningly as if it were used as some part of a loop. There should be
no necessity to write a loop to process the elements in a sequence.
 
S

Steven T. Hatton

Dietmar said:
Steven T. Hatton wrote: [...]
When there is a reasonably good
open standard, I believe its best to adopt it, rather than use something
that will not work with programs that do adhere to the standard.

Interoperability and portability are two different things. It may well
be reasonable to create own libraries and use these within a community
rather than using what the rest of world uses. In fact, there are
clearly several rather different styles of programmin C++ anyway. The
"MFC style" and the "STL style" are rather different approaches. Also,
some people will disagree with my assessment that the generic approach
is the way to go and prefer an object oriented approach. It is a free
world and everybody is entitled to seek his luck where he thinks he'll
find it - they'd just better not complain to me about seeking it in
object orientation and not finding it there because I told them :)

I don't see it as one way or another. It really depends when you need the
polymorphism, and which is better at expressing a particular concept. I
still haven't sorted all this out (and I wonder who has). Templates can be
very flexible at compile time. Their type checking can be both a boon and
a bane. It's often exactly the behavior you want when the compiler refuses
to compare or assign two distinct types. OTOH, if you really do want two
types of templated objects to be assignable and comparable, you have to do
a bit of extra work, and you have to understand how to work with templates
fairly well.

You mean in opening a market for other libraries?

I was really speaking in more general terms, meaning that it provides a good
lean foundation to build upon.
Especially with respect to threading, it is generally accepted that it
cannot be done by a library alone. The compiler also has to make certain
guarantees about reordering of statements. I think that the direction
championed by Andrei Alexandrescu and Hans Boehm which builds upon ideas
from the "lock free multi-threading" community is the right way to go
but I have no idea whether this is too avantgarde - I hope it is not.

Perhaps I have the advantage of not having too many preconceived notions of
how it should be done. I will say the Java approach to threading was easy
for me to grasp.
... but then, the C++ committee got hurt at the leading edge before
(although STL is a huge success, there were also many problems introduced
by standardizing features nobody had experience with; although this does
not that badly apply to STL itself but it clearly applies to features
which were necessary to make STL work).


Yes, but years later, C++ programmers are usually passionate advocate of the
STL.
STL is mostly about interoperability.

Many people will claim performance is also one of the primary advantage of
compile time polymorphism.
Thus it is only consistent to
provide facilities which allow interoperability with object oriented
features.

I need to get around to running some tests on algorithms using mem_fun
verses using for loops and static invocation.
In fact, generic programming is not about replacing object
oriented techniques but it is a complementary technique which is good
at things where object orientation is bad at (although some highly
religious object orientation believers will consider the indication
that object orientation is not the panacea as blasphemy - I don't mind
since I intend to go to object orientation hell, i.e. to generic
programming heaven :)

The hardest thing for me to deal with when it comes to generic programming
has been the fact that the concept is often not clear from the context.
With traditional UDT programming, you can clearly see that the parameter
you are passing is of the correct type. With generic programming, we
encounter the problem of the type of the type parameter. There is no
programmatic way, that I understand, of expressing what a "pure
abstraction" is. I've heard of programming entities called "concepts", but
I know nothing about them.
[...]
Apparently, you haven't understood what STL is about ;-) There are just
a few kind of entities which are completely described by concepts with
the central concept (group) being the iterators.

I was considering the iterators to be integral to the containers.
Actually, STL
essentially revolves around iterators: they are used by the algorithms
and provided by the containers which decouples the algorithms from the
containers and allows independent realization of algorithms and
containers. BTW, containers are entirely irrelevant to STL. STL
operates on sequences, not containers. There is a huge conceptual
difference between these two.

I almost used the word "collection" because, to me, the STL "containers"
really aren't containers. This is especially true of vector and deque. I
would not even use the term "sequence". To me, "sequence" suggests the
elements under discussion have some inherent ordering. The relevant
ordering comes about when the iterator is incremented. It is defined
externally from the data. I would rather call the things being visited
during an iteration "enumerable elements".
Yes, this is essentially it: cursors provide a position and some form
of a "key" and a property map provides values associated with the "key".
However, the "key" can be just an index into a vector or a reference to
the value itself. How the property map accesses a value related to a
key is entirely up to the property map. In particular, you should rather
envision an index lookup than a lookup in map or a has, i.e. the
property map access should be considered to be a cheap O(1) access
although it may be more involved.

Actually, I didn't understand what you meant. I was thinking of the
"properties" as being things such as the size, type of element, iterators
available, etc.
I don't think it is but I'm not sure. I'd consider it more important
to work on some form of lambda expressions because this would remove
the need to name these types in the first place! The above looks
cunningly as if it were used as some part of a loop. There should be
no necessity to write a loop to process the elements in a sequence.

I was actually thinking in more general terms of being able to access the
typedefs inside a class through an instance. But that might run contrary to
concepts of OO and polymorphism. The example was probably most applicable
to a loop. The suggestion that lambda expression can do away with loops is
fully convincing to me. Whether you do away with the body of the loop or
not, you have two choices when processing a collection one at a time.
Iteration or recursion. There may be some good arguments for using
recursion in some cases. In general, it is not as efficient. The only
thing you accomplish with a lambda in a typical STL algorithm is to hide
the loop in the algorithm implementation.

I'm pretty sure the way lambda expressions will work is similar to the way
Mathematica works. That is significantly different than the way
traditional C++ works. Functional programming is not an intuiteve art for
me. I've done some fun stuff with it, but it usually requires more careful
thought than writing out a proceedural block of code.
 
C

Calum Grant

Panjandrum said:
Whenever possible the KISS way should be used and not the STL/Boost
MICI (make it complicated and impenetrable) way.

These two principles (KISS + adhering to standards) aren't necessarily
incompatible.

Believe it or not, the STL is supposed to be easy to use. Or at least,
easier than not using the STL. For example, std::string is simpler than
char*, and std::vector is simpler than a C array.

I agree, its syntax could be a lot nicer, but I believe its benefits
outweigh its complexity.

Seeing how the STL is standard, you just have to learn to like it.

There are two choices in library design:
1) Pre-templates: contained values are void*
2) Post-templates: containers are templated.

The advantages of 2 are: type-safety, no casts needed in client code,
faster code.

Alternatively, don't use C++, use a typeless language like Python. C++
as a whole does not adhere to KISS, but I believe the complexity is
worth it.
 
D

Donovan Rebbechi

I've been using Qt based products since 1997 when the KDE was still in
alpha. I don't believe Trolltech have significant misgivings about the
core design of their libraries, and since they reinvent the blinkin' thing
about once every two years, whatever they would have done differently, has
been done differently.

Not necessarily. Why discard work that they've already done ? They may have
chosen not to do it in the first place, but now that it's there, it may be
advantageous for them to keep it. For example, the QTL has the advantage, for
them (Trolltech), of being controlled by them, and having some design features
that are appropriate for use in a GUI toolkit. For example, they are pointer-based,
as opposed to value-based STL containers. They use the derive-from-void* trick
to avoid template bloat (one of the advantages of Qt is that it avoids compile
time dependencies -- so this is consistent with that philosophy)

And in some cases, it may really be too much work to take another approach. For
example, implementing a template based signal/slot architecture would amount to
a rewrite of the toolkit.
I don't belive the QTL will fit that category. The functionality offered in
their API is arguably superior to that of the Standard, and the Standard
doesn't specify implementation.

They have improved their container classes (learned from STL, I suppose) but
earlier versions suffered from a number of problems:

(1) bloated interfaces (count the member functions, compare to STL classes) this
is even true of newer versions
(2) earlier versions enabled fairly badly broken element access. For example, I
consider a "random access interface" to a linked list to be a conceptual
error. If you're using indices to access elements of a linked list, you don't
understand what a linked list is, and you're using the wrong data structure.
Use a dynamic array, a hashtable, or a tree based map instead. Also, the
"current item" they had in the previous versions is a broken way to do element
access. It needlessly fattens the interface, and it also unnecessarily modifies
the state of the list (by storing state information that should be decoupled
from the list)

(3) why virtual functions ? Does it make sense to use these classes polymorphically ?
I disagree. There really is nothing in Qt that is not implemented using
Standard C++.

What I meant was, it can't be based on "standard C++", because there was no standard
C++ available at the time it was implemented. So in that sense, the existence of
a "standard C++" was not a premise for the design. Of course it builds against
"standard C++" compilers (to the extent that such things exist), but it wasn't
*designed* against a backdrop of todays standard.

[snip]
As for QString verses std::string, the advantage std::string has is that
it's standard. Beyond that, I don't believe it even comes close to
QString, and that doesn't even address QStringList.

I don't believe in the "more features is better" principle. Both classes are
somewhat bloated.

Cheers,
 
P

Panjandrum

Calum said:
Believe it or not, the STL is supposed to be easy to use. Or at least,
easier than not using the STL.

If STL were easy to use it would be used more widely.
For example, std::string is simpler than
char*, and std::vector is simpler than a C array.

Agreed (except that std::string is not part of STL). But you compare
apples to oranges (C to C++). Comparing one C++ approach (STL) to other
approaches would be more revealing.
I agree, its syntax could be a lot nicer, but I believe its benefits
outweigh its complexity.

Seeing how the STL is standard, you just have to learn to like it.

That's the wrong way. You don't start to like something just because
it's 'standard'.
There are two choices in library design:
1) Pre-templates: contained values are void*
2) Post-templates: containers are templated.

.... and others. But even if you are right it doesn't mean that
STL/Boost is the only way how templates are to be used.
The advantages of 2 are: type-safety, no casts needed in client code,
faster code.

Alternatively, don't use C++, use a typeless language like Python. C++
as a whole does not adhere to KISS, but I believe the complexity is
worth it.

Alternatively, you can use easier approaches within C++. At least, C++
is touted as "Multiparadigm" language, not as STL/Boost paradigm
language.
 
D

Donovan Rebbechi

If STL were easy to use it would be used more widely.

It takes time for things to be "used widely". First, the early adopters use
it. Then people write books on it. Then it is more widely learned, since all
the books cover it. Then new projects (but not necessarily old projects) start
using it. Then the new projects gain visibility. I'm not convinced that STL
is not more widely used because it's "too hard" to use.
Agreed (except that std::string is not part of STL). But you compare
apples to oranges (C to C++). Comparing one C++ approach (STL) to other
approaches would be more revealing.

What are some of these approaches, and what advantages do they have over
STL ?
... and others. But even if you are right it doesn't mean that
STL/Boost is the only way how templates are to be used.

What other ways did you have in mind ?

Cheers,
 
S

Steven T. Hatton

Donovan said:
Not necessarily. Why discard work that they've already done ?

Qt 4 has significantly redesigned container classes. They don't call it QTL
anymore. It's called Tulip.

[...]
For
example, they are pointer-based, as opposed to value-based STL containers.

Some of the QTL containers were pointer based, but they did away with those.
They use the derive-from-void* trick to avoid template bloat (one of the
advantages of Qt is that it avoids compile time dependencies -- so this is
consistent with that philosophy)

I'm not sure what you mean by "derive from void", but I don't believe it
applies to the current release.
And in some cases, it may really be too much work to take another
approach. For example, implementing a template based signal/slot
architecture would amount to a rewrite of the toolkit.

They claim to not be interested in implementing signals and slots using
templates, saying the current approach is easier to understand.
They have improved their container classes (learned from STL, I suppose)
but earlier versions suffered from a number of problems:

(1) bloated interfaces (count the member functions, compare to STL
classes) this is even true of newer versions

Considering they provide both the STL names with under_scores, and the Qt
style synonyms with mixedCase, and arguably better meaning, I don't see a
problem. It's not as if that adds to the size of your code or the compiled
result. It simply enables you to produce a consistent API or program with
a uniform naming system.
(2) earlier versions enabled fairly badly broken element access. For
example, I
consider a "random access interface" to a linked list to be a
conceptual error. If you're using indices to access elements of a
linked list, you don't understand what a linked list is, and you're
using the wrong data structure. Use a dynamic array, a hashtable, or a
tree based map instead. Also, the "current item" they had in the
previous versions is a broken way to do element access. It needlessly
fattens the interface, and it also unnecessarily modifies the state of
the list (by storing state information that should be decoupled from
the list)

You seem to be making my original point for me. "whatever they would have
done differently, has been done differently." Bear in mind they have QList
and QLinkedList. QList is the counterpart of the STL deque.
(3) why virtual functions ? Does it make sense to use these classes
polymorphically ?

It may have seemed like a possibility they wanted to leave open at the time.
There's nothing like that in the current Qt containers I've looked at.
What I meant was, it can't be based on "standard C++", because there was
no standard C++ available at the time it was implemented. So in that
sense, the existence of a "standard C++" was not a premise for the design.
Of course it builds against "standard C++" compilers (to the extent that
such things exist), but it wasn't *designed* against a backdrop of todays
standard.

The current Qt is not the same as the original Qt. It has been
significantly redesigned more than once.
[snip]
As for QString verses std::string, the advantage std::string has is that
it's standard. Beyond that, I don't believe it even comes close to
QString, and that doesn't even address QStringList.

I don't believe in the "more features is better" principle. Both classes
are somewhat bloated.

Cheers,

To me it's not a question of applying some management metric such as how
many functions there are on the interface. It's a question of whether it
does what I need without having to bend over backwords to make it work.
 
D

Donovan Rebbechi

I'm not sure what you mean by "derive from void", but I don't believe it
applies to the current release.

I mean that you can implement a container of pointers in terms of a container
of void pointers. You avoid template bloat by doing this, because the
parametrised version of the class is reduced to a thin type-safety wrapper.
They claim to not be interested in implementing signals and slots using
templates, saying the current approach is easier to understand.

I've read what they claim, and I believe my point still stands. It doesn't
make a lot of sense for them to throw away all their metaobject
infrastructure -- now that it works, and is a mature system. But they do
also say that the state of compilers (and support for templates) at the
time was part of the reason that they did it that way in the first place.
Considering they provide both the STL names with under_scores, and the Qt
style synonyms with mixedCase, and arguably better meaning, I don't see a
problem.

Oh dear, I didn't even know they did that. That's even worse than I thought.
It's not as if that adds to the size of your code or the compiled
result. It simply enables you to produce a consistent API or program with
a uniform naming system.

It also facilitates inconsistency.

But that's not what I was referring to anyway. I was referring to classes
with an enormous number of member functions.
You seem to be making my original point for me. "whatever they would have
done differently, has been done differently."

No. That is a single example, and a fairly small part of the toolkit.
It may have seemed like a possibility they wanted to leave open at the time.

Yes, exactly. Still, I hope I've convinced you that at least in earlier
iterations of their toolkit, they really did have some glaring flaws (though
they appear to have learned)
There's nothing like that in the current Qt containers I've looked at.

Yes, I think generally, people have learned from STL. It's not just a good
container library, it's also a good example of how to approach writing a
templated container library.
The current Qt is not the same as the original Qt. It has been
significantly redesigned more than once.

How has it been "significantly redesigned" ? I don't consider breaking binary
compatibility to be a redesign. It still uses MOC, string based signals and
slots, and much the same class heirarchy, right ?
To me it's not a question of applying some management metric such as how
many functions there are on the interface.

It's not just a "management metric". There are actually reasons that coding
guidelines like these exist. As far as bloated interfaces go, there are a
number of issues. This is discussed in Scott Meyers under "make interfaces
minimal and complete". I don't have the book, but here are some reasons I
don't like bloated interfaces:

(1) it makes the interface harder to learn, because there's more stuff there.
Of course you can just learn a subset of the interface, which works fine
until you have to read someone else's code (this is the reason why perl code
is often considered unscrutable -- "there's more than one way to do it" is
misguidedly elevated to a design principle).

(2) it increases the likelihood that there are several ways to do the same
thing, which leads to inconsistent code

(3) it increases the likelihood that the class interface will need to be
changed. For example, when you have member functions like currentItem(), and
operator[] in a linked list class you are locking in some really poor design
choices. In the case of Qt, the result was that they decided the class needed
to be thrown out. In the case of QString, it means that they have a bunch of
legacy crud in the interface, which they will probably drop. Of course,
Trolltech have the option of rewriting classes that they botch. The standards
committee don't.

(4) it violates the principal of minimal coupling/l;east privelige. Let's
explore this a little further. In some computer science text books, examples of
linked lists include member functions like print(). Often, these bad linked
list classes offer no way to do element access without resorting to adding
private member functions (not an option in the real world!) or using indices
(clunk!)

So when you have functions like replace(), find(), etc, either
(a) they don't need to be member functions (so they shouldn't be)
(b) they do need to be member functions, which indicates a problem with the
design of the class (since adding basic functionality is impossible without
accss to private members.

It's a question of whether it does what I need without having to bend over
backwords to make it work.

Well, despite its flaws, both std::string and QString are both quite useable.

Cheers,
 
C

Calum Grant

Panjandrum said:
If STL were easy to use it would be used more widely.

I thought it was fairly universally used. Except for legacy code of course.
Agreed (except that std::string is not part of STL). But you compare
apples to oranges (C to C++). Comparing one C++ approach (STL) to other
approaches would be more revealing.

What "other approaches" are there for representing an array? Something
based upon void* / CObject* would surely be worse?
That's the wrong way. You don't start to like something just because
it's 'standard'.

Okay, you're right. But the obvious question is: how would you improve
it? I mean, if you for example dropped templates, or iterators, what
would you replace them with?
... and others. But even if you are right it doesn't mean that
STL/Boost is the only way how templates are to be used.




Alternatively, you can use easier approaches within C++. At least, C++
is touted as "Multiparadigm" language, not as STL/Boost paradigm
language.

But I'm sure these "easier" approaches have some disadvantages. Anyway
which did you have in mind?
----
"Removing a pattern can simplify a system and a simple solution should
almost always win. Coming up with simple solutions is the real
challenge."
Erich Gamma

I love that quote. I'll be sure to spread it around work.

Calum
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,070
Latest member
BiogenixGummies

Latest Threads

Top