source: trunk/doc/src/templates.qdoc@ 321

Last change on this file since 321 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 12.9 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the documentation of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42/*!
43 \page templates.html
44 \title Why Doesn't Qt Use Templates for Signals and Slots?
45 \ingroup architecture
46 \brief The reasoning behind Qt's implementation of signals and slots.
47
48 Templates are a builtin mechanism in C++ that allows the compiler to
49 generate code on the fly, depending on the type of the arguments
50 passed. As such, templates are highly interesting to framework
51 creators, and we do use advanced templates in many places
52 in Qt. However, there are limitations: There are things that you can
53 easily express with templates, and there are things that are
54 impossible to express with templates. A generic vector container class
55 is easily expressible, even with partial specialisation for pointer
56 types, while a function that sets up a graphical user interface based
57 on a XML description given as a string is not expressible as
58 template. And then there is gray area in between. Things that you can
59 hack with templates at the cost of code size, readability,
60 portability, usability, extensability, robustness and ultimately
61 design beauty. Both templates and the C preprocessor can be stretched
62 to do incredibility smart and mind boggling things. But just because
63 those things can be done, does not necessarily mean doing them is the
64 right design choice.
65
66 There is an important practical challenge we have to mention: due to
67 the inadequacies of various compilers it is still not possible to
68 fully exploit the template mechanism in cross-platform
69 applications. Code unfortunately is not meant to be published in
70 books, but compiled with real-world compilers on real-world operating
71 system. Even today, many widely used C++ compilers have problems with
72 advanced templates. For example, you cannot safely rely on partial
73 template specialisation, which is essential for some non-trivial
74 problem domains. Some compilers also have limitations with regards to
75 template member functions, which make it hard to combine generic
76 programming with object orientated programming. However, we do not
77 perceive these problems as a serious limitation in our work. Even if
78 all our users had access to a fully standards compliant modern C++
79 compiler with excellent template support, we would not abandon the
80 string-based approach used by our meta object compiler for a template
81 based signals and slots system. Here are five reasons why:
82
83 \section1 Syntax matters
84
85 Syntax isn't just sugar: the syntax we use to express our algorithms can
86 significantly affect the readability and maintainability of our code.
87 The syntax used for Qt's signals and slots has proved very successful in
88 practice. The syntax is intuitive, simple to use and easy to read.
89 People learning Qt find the syntax helps them understand and utilize the
90 signals and slots concept -- despite its highly abstract and generic
91 nature. Furthermore, declaring signals in class definitions ensures that
92 the signals are protected in the sense of protected C++ member
93 functions. This helps programmers get their design right from the very
94 beginning, without even having to think about design patterns.
95
96 \section1 Code Generators are Good
97
98 Qt's \c{moc} (Meta Object Compiler) provides a clean way to go
99 beyond the compiled language's facilities. It does so by generating
100 additional C++ code which can be compiled by any standard C++ compiler.
101 The \c{moc} reads C++ source files. If it finds one or more class
102 declarations that contain the Q_OBJECT macro, it produces another C++
103 source file which contains the meta object code for those classes. The
104 C++ source file generated by the \c{moc} must be compiled and
105 linked with the implementation of the class (or it can be
106 \c{#included} into the class's source file). Typically \c{moc}
107 is not called manually, but automatically by the build system, so it
108 requires no additional effort by the programmer.
109
110 The \c{moc} is not the only code generator Qt is using. Another
111 prominent example is the \c{uic} (User Interface Compiler). It
112 takes a user interface description in XML and creates C++ code that
113 sets up the form. Outside Qt, code generators are common as well. Take
114 for example \c{rpc} and \c{idl}, that enable programs or
115 objects to communicate over process or machine boundaries. Or the vast
116 variety of scanner and parser generators, with \c{lex} and
117 \c{yacc} being the most well-known ones. They take a grammar
118 specification as input and generate code that implements a state
119 machine. The alternatives to code generators are hacked compilers,
120 proprietary languages or graphical programming tools with one-way
121 dialogs or wizards that generate obscure code during design time
122 rather than compile time. Rather than locking our customers into a
123 proprietary C++ compiler or into a particular Integrated Development
124 Environment, we enable them to use whatever tools they prefer. Instead
125 of forcing programmers to add generated code into source repositories,
126 we encourage them to add our tools to their build system: cleaner,
127 safer and more in the spirit of UNIX.
128
129
130 \section1 GUIs are Dynamic
131
132 C++ is a standarized, powerful and elaborate general-purpose language.
133 It's the only language that is exploited on such a wide range of
134 software projects, spanning every kind of application from entire
135 operating systems, database servers and high end graphics
136 applications to common desktop applications. One of the keys to C++'s
137 success is its scalable language design that focuses on maximum
138 performance and minimal memory consumption whilst still maintaining
139 ANSI C compatibility.
140
141 For all these advantages, there are some downsides. For C++, the static
142 object model is a clear disadvantage over the dynamic messaging approach
143 of Objective C when it comes to component-based graphical user interface
144 programming. What's good for a high end database server or an operating
145 system isn't necessarily the right design choice for a GUI frontend.
146 With \c{moc}, we have turned this disadvantage into an advantage,
147 and added the flexibility required to meet the challenge of safe and
148 efficient graphical user interface programming.
149
150 Our approach goes far beyond anything you can do with templates. For
151 example, we can have object properties. And we can have overloaded
152 signals and slots, which feels natural when programming in a language
153 where overloads are a key concept. Our signals add zero bytes to the
154 size of a class instance, which means we can add new signals without
155 breaking binary compatibility. Because we do not rely on excessive
156 inlining as done with templates, we can keep the code size smaller.
157 Adding new connections just expands to a simple function call rather
158 than a complex template function.
159
160 Another benefit is that we can explore an object's signals and slots at
161 runtime. We can establish connections using type-safe call-by-name,
162 without having to know the exact types of the objects we are connecting.
163 This is impossible with a template based solution. This kind of runtime
164 introspection opens up new possibilities, for example GUIs that are
165 generated and connected from Qt Designer's XML \c{ui} files.
166
167 \section1 Calling Performance is Not Everything
168
169 Qt's signals and slots implementation is not as fast as a
170 template-based solution. While emitting a signal is approximately the
171 cost of four ordinary function calls with common template
172 implementations, Qt requires effort comparable to about ten function
173 calls. This is not surprising since the Qt mechanism includes a
174 generic marshaller, introspection, queued calls between different
175 threads, and ultimately scriptability. It does not rely on excessive
176 inlining and code expansion and it provides unmatched runtime
177 safety. Qt's iterators are safe while those of faster template-based
178 systems are not. Even during the process of emitting a signal to
179 several receivers, those receivers can be deleted safely without your
180 program crashing. Without this safety, your application would
181 eventually crash with a difficult to debug free'd memory read or write
182 error.
183
184 Nonetheless, couldn't a template-based solution improve the performance
185 of an application using signals and slots? While it is true that Qt adds
186 a small overhead to the cost of calling a slot through a signal, the
187 cost of the call is only a small proportion of the entire cost of a
188 slot. Benchmarking against Qt's signals and slots system is typically
189 done with empty slots. As soon as you do anything useful in your slots,
190 for example a few simple string operations, the calling overhead becomes
191 negligible. Qt's system is so optimized that anything that requires
192 operator new or delete (for example, string operations or
193 inserting/removing something from a template container) is significantly
194 more expensive than emitting a signal.
195
196 Aside: If you have a signals and slots connection in a tight inner loop
197 of a performance critical task and you identify this connection as the
198 bottleneck, think about using the standard listener-interface pattern
199 rather than signals and slots. In cases where this occurs, you probably
200 only require a 1:1 connection anyway. For example, if you have an object
201 that downloads data from the network, it's a perfectly sensible design
202 to use a signal to indicate that the requested data arrived. But if you
203 need to send out every single byte one by one to a consumer, use a
204 listener interface rather than signals and slots.
205
206 \section1 No Limits
207
208 Because we had the \c{moc} for signals and slots, we could add
209 other useful things to it that could not be done with templates.
210 Among these are scoped translations via a generated \c{tr()}
211 function, and an advanced property system with introspection and
212 extended runtime type information. The property system alone is a
213 great advantage: a powerful and generic user interface design tool
214 like Qt Designer would be a lot harder to write - if not impossible -
215 without a powerful and introspective property system. But it does not
216 end here. We also provide a dynamic qobject_cast<T>() mechanism
217 that does not rely on the system's RTTI and thus does not share its
218 limitations. We use it to safely query interfaces from dynamically
219 loaded components. Another application domain are dynamic meta
220 objects. We can e.g. take ActiveX components and at runtime create a
221 meta object around it. Or we can export Qt components as ActiveX
222 components by exporting its meta object. You cannot do either of these
223 things with templates.
224
225 C++ with the \c{moc} essentially gives us the flexibility of
226 Objective-C or of a Java Runtime Environment, while maintaining C++'s
227 unique performance and scalability advantages. It is what makes Qt the
228 flexible and comfortable tool we have today.
229
230*/
Note: See TracBrowser for help on using the repository browser.