|
Packit |
1c1d7e |
/****************************************************************************
|
|
Packit |
1c1d7e |
**
|
|
Packit |
1c1d7e |
**
|
|
Packit |
1c1d7e |
** Qt template library classes documentation
|
|
Packit |
1c1d7e |
**
|
|
Packit |
1c1d7e |
** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.
|
|
Packit |
1c1d7e |
**
|
|
Packit |
1c1d7e |
** This file is part of the Qt GUI Toolkit.
|
|
Packit |
1c1d7e |
**
|
|
Packit |
1c1d7e |
** This file may be distributed under the terms of the Q Public License
|
|
Packit |
1c1d7e |
** as defined by Trolltech AS of Norway and appearing in the file
|
|
Packit |
1c1d7e |
** LICENSE.QPL included in the packaging of this file.
|
|
Packit |
1c1d7e |
**
|
|
Packit |
1c1d7e |
** This file may be distributed and/or modified under the terms of the
|
|
Packit |
1c1d7e |
** GNU General Public License version 2 as published by the Free Software
|
|
Packit |
1c1d7e |
** Foundation and appearing in the file LICENSE.GPL included in the
|
|
Packit |
1c1d7e |
** packaging of this file.
|
|
Packit |
1c1d7e |
**
|
|
Packit |
1c1d7e |
** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
|
|
Packit |
1c1d7e |
** licenses may use this file in accordance with the Qt Commercial License
|
|
Packit |
1c1d7e |
** Agreement provided with the Software.
|
|
Packit |
1c1d7e |
**
|
|
Packit |
1c1d7e |
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
|
Packit |
1c1d7e |
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
|
Packit |
1c1d7e |
**
|
|
Packit |
1c1d7e |
** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
|
|
Packit |
1c1d7e |
** information about Qt Commercial License Agreements.
|
|
Packit |
1c1d7e |
** See http://www.trolltech.com/qpl/ for QPL licensing information.
|
|
Packit |
1c1d7e |
** See http://www.trolltech.com/gpl/ for GPL licensing information.
|
|
Packit |
1c1d7e |
**
|
|
Packit |
1c1d7e |
** Contact info@trolltech.com if any conditions of this licensing are
|
|
Packit |
1c1d7e |
** not clear to you.
|
|
Packit |
1c1d7e |
**
|
|
Packit |
1c1d7e |
**********************************************************************/
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
/*!
|
|
Packit |
1c1d7e |
\page qtl.html
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
\title Qt Template library
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
Thq Qt Template Library is a set of templates within Qt dealing with
|
|
Packit |
1c1d7e |
containers of objects. It provides a list of objects, a stack of
|
|
Packit |
1c1d7e |
objects, a map (or dictionary) from one type to another, and
|
|
Packit |
1c1d7e |
associated iterators and algorithms.
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
Qt also contains similar classes that deal with pointers to objects;
|
|
Packit |
1c1d7e |
\l QValueList vs. \l QList, etc. Compared to the pointer-based
|
|
Packit |
1c1d7e |
templates, the QTL offers easy copying of the container, real support
|
|
Packit |
1c1d7e |
for classes that e.g. require constructors, expand to much more object
|
|
Packit |
1c1d7e |
code, can often be a bit faster, require that the objects stored can
|
|
Packit |
1c1d7e |
be copied, and finally, have a worse record of compiler problems.
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
Compared to the STL, the QTL contains only the most important features
|
|
Packit |
1c1d7e |
of the STL, has more regular function naming, has no platform
|
|
Packit |
1c1d7e |
differences, is often a little slower and often expands to less object
|
|
Packit |
1c1d7e |
code.
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
If you can not make copies of the objects you want to store you are
|
|
Packit |
1c1d7e |
better off with QCollection and friends. They were designed to handle
|
|
Packit |
1c1d7e |
exactly that kind of pointer semantics. This applies for example to
|
|
Packit |
1c1d7e |
all classes derived from \l QObject. A QObject does not have a copy
|
|
Packit |
1c1d7e |
constructor, so using it as value is impossible. You may choose be
|
|
Packit |
1c1d7e |
store pointers to QObjects in a QValueList, but using QList directly
|
|
Packit |
1c1d7e |
seems to be the better choice for this kind of application
|
|
Packit |
1c1d7e |
domain. QList, like all other QCollection based containers, provides
|
|
Packit |
1c1d7e |
far more sanity checking than a speed-optimized value
|
|
Packit |
1c1d7e |
based container.
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
If you have objects that implement value semantics, use the Qt
|
|
Packit |
1c1d7e |
template library. Value semantics require at least
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
a copy constructor,
|
|
Packit |
1c1d7e |
an assignment operator and
|
|
Packit |
1c1d7e |
a default constructor, i.e. a constructor that does not take
|
|
Packit |
1c1d7e |
any arguments.
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
Note that a fast copy constructor is absolutely crucial for a good
|
|
Packit |
1c1d7e |
overall performance of the container, since many copy operations are
|
|
Packit |
1c1d7e |
going to happen.
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
Examples for value based classes are QRect, QPoint, QSize and all
|
|
Packit |
1c1d7e |
simple C++ types like int, bool or double.
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
The Qt template library is designed for speed. Especially iterators
|
|
Packit |
1c1d7e |
are extremely fast. On the drawback side, less error checking is done
|
|
Packit |
1c1d7e |
than in the QCollection based containers. A template library container
|
|
Packit |
1c1d7e |
for example does not track associated iterators. This makes certain
|
|
Packit |
1c1d7e |
validity checks, like on removing items, impossible to perform
|
|
Packit |
1c1d7e |
automatically.
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
Iterators
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
The Qt template library deals with value objects, not with pointers.
|
|
Packit |
1c1d7e |
For that reason, there is no other way of iterating over containers
|
|
Packit |
1c1d7e |
than using iterators. This is no disadvantage as the size of an
|
|
Packit |
1c1d7e |
iterator matches the size of a normal pointer - 32 or 64 bits
|
|
Packit |
1c1d7e |
depending on your CPU architecture.
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
To iterate over a container, use a loop like this:
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
\code
|
|
Packit |
1c1d7e |
typedef QValueList<int> List;
|
|
Packit |
1c1d7e |
List l;
|
|
Packit |
1c1d7e |
for( List::Iterator it = l.begin(); it != l.end(); ++it )
|
|
Packit |
1c1d7e |
printf("Number is %i\n",*it);
|
|
Packit |
1c1d7e |
\endcode
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
begin() returns the iterator pointing at the first element, while
|
|
Packit |
1c1d7e |
end() returns an iterator that points \e after the last
|
|
Packit |
1c1d7e |
element. end() marks an invalid position, it can never be
|
|
Packit |
1c1d7e |
dereferenced. It's the break condition in any iteration, may it be
|
|
Packit |
1c1d7e |
from begin() or fromLast(). For maximum speed, use increment or
|
|
Packit |
1c1d7e |
decrement iterators with the prefix operator (++it, --it) instead of the the
|
|
Packit |
1c1d7e |
postfix one (it++, it--), since the former is slightly faster.
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
The same concept applies to the other container classes:
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
\code
|
|
Packit |
1c1d7e |
typedef QMap<QString,QString> Map;
|
|
Packit |
1c1d7e |
Map map;
|
|
Packit |
1c1d7e |
for( Map::Iterator it = map.begin(); it != map.end(); ++it )
|
|
Packit |
1c1d7e |
printf("Key=%s Data=%s\n", it.key().ascii(), it.data().ascii() );
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
typedef QArray<int> Array;
|
|
Packit |
1c1d7e |
Array array;
|
|
Packit |
1c1d7e |
for( Array::Iterator it = array.begin(); it != array.end(); ++it )
|
|
Packit |
1c1d7e |
printf("Data=%i\n", *it );
|
|
Packit |
1c1d7e |
\endcode
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
There are two kind of iterators, the volatile iterator shown in the
|
|
Packit |
1c1d7e |
examples above and a version that returns a const reference to its
|
|
Packit |
1c1d7e |
current object, the ConstIterator. Const iterators are required
|
|
Packit |
1c1d7e |
whenever the container itself is const, such as a member variable
|
|
Packit |
1c1d7e |
inside a const function. Assigning a ConstIterator to a normal
|
|
Packit |
1c1d7e |
Iterator is not allowed as it would violate const semantics.
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
Algorithms
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
The template library defines a number of algorithms that operate on
|
|
Packit |
1c1d7e |
its containers: qHeapSort(), qBubbleSort(), qSwap() and
|
|
Packit |
1c1d7e |
qCopy(). These algorithms are implemented as template functions.
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
qHeapSort() and qBubbleSort() provide the well known sorting
|
|
Packit |
1c1d7e |
algorithms. You can use them like this:
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
\code
|
|
Packit |
1c1d7e |
typedef QValueList<int> List;
|
|
Packit |
1c1d7e |
List l;
|
|
Packit |
1c1d7e |
l << 42 << 100 << 1234 << 12 << 8;
|
|
Packit |
1c1d7e |
qHeapSort( l );
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
List l2;
|
|
Packit |
1c1d7e |
l2 << 42 << 100 << 1234 << 12 << 8;
|
|
Packit |
1c1d7e |
List::Iterator b = l2.find( 100 );
|
|
Packit |
1c1d7e |
List::Iterator e = l2.find( 8 );
|
|
Packit |
1c1d7e |
qHeapSort( b, e );
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
double arr[] = { 3.2, 5.6, 8.9 };
|
|
Packit |
1c1d7e |
qHeapSort( arr, arr + 3 );
|
|
Packit |
1c1d7e |
\endcode
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
The first example sorts the entire list. The second one sorts all
|
|
Packit |
1c1d7e |
elements enclosed in the two iterators, namely 100, 1234 and 12. The
|
|
Packit |
1c1d7e |
third example shows that iterators act like pointers and can be
|
|
Packit |
1c1d7e |
treated as such.
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
Naturally, the sorting templates won't work with const iterators.
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
Another utility is qSwap(). It exchanges the values of two variables:
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
\code
|
|
Packit |
1c1d7e |
QString second( "Einstein" );
|
|
Packit |
1c1d7e |
QString name( "Albert" );
|
|
Packit |
1c1d7e |
qSwap( second, name );
|
|
Packit |
1c1d7e |
\endcode
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
Another template function is qCopy(). It copies a container or a slice
|
|
Packit |
1c1d7e |
of it to an OutputIterator, in this case a QTextOStreamIterator:
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
\code
|
|
Packit |
1c1d7e |
typedef QValueList<int> List;
|
|
Packit |
1c1d7e |
List l;
|
|
Packit |
1c1d7e |
l << 100 << 200 << 300;
|
|
Packit |
1c1d7e |
QTextOStream str( stdout );
|
|
Packit |
1c1d7e |
qCopy( l, QTextOStreamIterator( str ) );
|
|
Packit |
1c1d7e |
\endcode
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
In addition, you can use any Qt template library iterator as the
|
|
Packit |
1c1d7e |
OutputIterator. Just make sure that the right hand of the iterator has
|
|
Packit |
1c1d7e |
as many elements present as you want to insert. The following example
|
|
Packit |
1c1d7e |
illustrates this:
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
\code
|
|
Packit |
1c1d7e |
QStringList l1, l2;
|
|
Packit |
1c1d7e |
l1 << "Weis" << "Ettrich" << "Arnt" << "Sue";
|
|
Packit |
1c1d7e |
l2 << "Torben" << "Matthias";
|
|
Packit |
1c1d7e |
qCopy( l2, l1.begin();
|
|
Packit |
1c1d7e |
\endcode
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
At the end of this code fragment, the List l1 contains "Torben",
|
|
Packit |
1c1d7e |
"Matthias", "Arnt" and "Sue", with the prior contents being
|
|
Packit |
1c1d7e |
overwritten. Another flavor of qCopy() takes three arguments to make
|
|
Packit |
1c1d7e |
it possible to copy a slice of a container:
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
\code
|
|
Packit |
1c1d7e |
typedef QValueList<int> List;
|
|
Packit |
1c1d7e |
List l;
|
|
Packit |
1c1d7e |
l << 42 << 100 << 1234 << 12 << 8;
|
|
Packit |
1c1d7e |
List::Iterator b = l.find( 100 );
|
|
Packit |
1c1d7e |
List::Iterator e = l.find( 8 );
|
|
Packit |
1c1d7e |
QTextOStream str( stdout );
|
|
Packit |
1c1d7e |
qCopy( b, e, QTextOStreamIterator( str ) );
|
|
Packit |
1c1d7e |
\endcode
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
If you write new algorithms, consider writing them as template
|
|
Packit |
1c1d7e |
functions in order to make them usable with as many containers
|
|
Packit |
1c1d7e |
possible. In the above example, you could just as easily print out a
|
|
Packit |
1c1d7e |
standard C++ array with qCopy():
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
\code
|
|
Packit |
1c1d7e |
int arr[] = { 100, 200, 300 };
|
|
Packit |
1c1d7e |
QTextOStream str( stdout );
|
|
Packit |
1c1d7e |
qCopy( arr, arr + 3, QTextOStreamIterator( str ) );
|
|
Packit |
1c1d7e |
\endcode
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
Streaming
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
All mentioned containers can be serialized with the respective
|
|
Packit |
1c1d7e |
streaming operators. Here is an example.
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
\code
|
|
Packit |
1c1d7e |
QDataStream str(...);
|
|
Packit |
1c1d7e |
QValueList<QRect> l;
|
|
Packit |
1c1d7e |
// ... fill the list here
|
|
Packit |
1c1d7e |
str << l;
|
|
Packit |
1c1d7e |
\endcode
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
The container can be read in again with:
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
\code
|
|
Packit |
1c1d7e |
QValueList<QRect> l;
|
|
Packit |
1c1d7e |
str >> l;
|
|
Packit |
1c1d7e |
\endcode
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
The same applies to QStringList, QValueStack and QMap.
|
|
Packit |
1c1d7e |
|
|
Packit |
1c1d7e |
*/
|