[Development] Header file cleanups

Thiago Macieira thiago.macieira at intel.com
Thu Mar 1 13:47:53 CET 2012


On quinta-feira, 1 de março de 2012 12.44.47, Mathias Hasselmann wrote:
> > According to the book it is. But in practice it happens all the time, and
> > we know it.
> 
> To which book? C++ compilers and IDEs give zero support in enforcing
> direct includes. Considering the mess GNU libc headers are, I even
> wonder how to formulate automatic checks for direct includes.

Adding includes is also a source-incompatible change in some situations and we 
can't avoid it. Adding a new include means new symbols become defined, new 
overloads are produced.

For example, the following code, found in WebKit, compiles under C++98 + POSIX 
or C++98 + C99:

	#include <cmath>
	using namespace std;
	int foo() { return isnan(0.); }

But it does not compile under C++11 because there's now a std::isnan. It 
happens because cmath indirectly includes math.h, which strictly speaking it 
shouldn't.

Another example of things breaking are Q_DECLARE_METATYPE. If you #include a 
header that declares a certain type a metatype, you'll break everyone's code 
that also had that macro.

> Considering this weakness of C and C++ some have come to the conclusion
> that indirect includes are part of the API. Removing redundant include
> directives from released headers actually is an API break in C/C++.

Which is why I am saying that, in my book, those changes are acceptable and 
user code will need to adapt. Therefore, they don't count as an API break. If 
you need to use feature X, you need to #include the header that provides it 
and you need to link to the library that contains it. Depending on indirect 
inclusion and on indirect linking is a bug.

Fortunately, for indirect linking the linker usually complains so those 
mistakes don't go far.

> The GNOME guys went the pragmatic approach and now forbid direct
> includes. You always must include the module headers for GTK+ and
> friends now (unless explicitly asking for trouble):
> 
>         #if !defined (__GTK_H_INSIDE__) && !defined (GTK_COMPILATION)
>         #error "Only <gtk/gtk.h> can be included directly."
>         #endif
> 
> Sadly, considering the slowness of g++ and the complexity of Qt, I doubt
> this is a reasonable approach for Qt.

Yup.

$ perf stat -d -r 10 g++ -fPIE -DQT_SHARED -c -o /dev/null \
	-I$QTOBJDIR/include -include QtWidgets/QtWidgets \
	-include QtNetwork/QtNetwork -xc++ /dev/null

       1043.329965 task-clock                #    0.997 CPUs utilized            
( +-  1.76% )
     3,397,699,525 cycles                    #    3.257 GHz                      
( +-  1.60% ) [40.11%]

       1.045980458 seconds time elapsed                                          
( +-  1.76% )

This is with an SSD.

-- 
Thiago Macieira - thiago.macieira (AT) intel.com
  Software Architect - Intel Open Source Technology Center
     Intel Sweden AB - Registration Number: 556189-6027
     Knarrarnäsgatan 15, 164 40 Kista, Stockholm, Sweden
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 190 bytes
Desc: This is a digitally signed message part.
URL: <http://lists.qt-project.org/pipermail/development/attachments/20120301/259c8409/attachment.sig>


More information about the Development mailing list