Qt In Namespace: Difference between revisions

From Qt Wiki
Jump to navigation Jump to search
(Add "cleanup" tag)
m (Link to article, not category)
(One intermediate revision by the same user not shown)
Line 1: Line 1:
{{Cleanup | reason=Auto-imported from ExpressionEngine.}}
[[Category:Developing_Qt::Guidelines]]
[[Category:Developing_Qt::Guidelines]]


Line 68: Line 66:
=== Related: ===
=== Related: ===


The [[Category:Tools::QtCreator|Qt Creator]] Debugger can handle namespaced code as if it were "native" Qt.
The [[Qt Creator]] Debugger can handle namespaced code as if it were "native" Qt.

Revision as of 14:43, 3 June 2016


The Qt-in-Namespace feature serves as a tool to handle certain scenarios involving multiple configurations of Qt more gracefully. E.g. before Qt-in-Namespace a Qt 3 based application in Linux would immediately segfault as soon as it tries to dlopen() a shared object that is linked to Qt 4. With the Qt in namespace feature not only can the crash be prevented, but under certain circumstances this combination might actually "work".

The core of the feature's implementation consists of wrapping "all of Qt code" into a pair of macros QT_BEGIN_NAMESPACE and QT_END_NAMESPACE. Both macros usually expand to nothing, but they expand to namespace xxx { and }, respectively, when Qt is configured with the option -qtnamespace xxx. The macros are defined in <qglobal.h>

The feature is part of Qt since Qt 4.4. Keeping the feature in a working state is, unfortunately, a bit tedious and influences code that gets integrated into Qt.

To help with this, all contributors to the Qt source code are kindly asked to follow the set of rules given below.

Rules for namespaced code:

This concerns code in main/src/{corelib,gui,…} and in main/tools/designer but not in main/src/3rdparty. As a rule of thumb: If it contributes to one of "the Qt" libraries that end up in lib/* and if it is "Qt" code, it is "namespaced code".

  1. All occurrences of QT_BEGIN_NAMESPACE and QT_END_NAMESPACE must be balanced with respect to #if/#ifdef etc. preprocessor directives. Most notably this applies to all QT_NO_<FEATURE> branches.
  2. All code that is not a preprocessor directive or a comment must be wrapped in QT_BEGIN_NAMESPACE and QT_END_NAMESPACE. As a rule of thumb this applies do all definitions and declarations concerning types, objects etc with identifiers starting with 'q' or 'Q'.
  3. All #include lines go outside the QT_BEGIN_NAMESPACE … QT_END_NAMESPACE.
  4. Forward declarations of items in non-namespaced code go outside.
  5. As a special exception QT_DECLARE_METATYPE lines go outside.
  6. Q_INIT_RESOURCE inside. However, the Makefile dependencies are inadequate, so make sure to remove all qrc_*.cpp files manually if you have troubles when "namespacing" old code.
  7. If we are in a header file there is usually already a QT_{BEGIN,END}_HEADER pair (or needs to be added) for other reasons. In this case QT_BEGIN_NAMESPACE follows immediately the QT_BEGIN_HEADER line, and QT_END_NAMESPACE precedes the QT_END_HEADER line. To be consistent in style with existing code there should be a single empty line between the QT_{BEGIN,END}_HEADER and QT_{BEGIN,END}_NAMESPACE lines.
  8. Since not all compilers we support adhere to The Standard we cannot use namespaced friend classes within some other class definition without declaring the friend class properly first. As a workaround, declare the friend class first within a QT_{BEGIN,END}_HEADER block.
  9. Since not all compilers we support adhere to The Standard we cannot declare external functions locally within other functions. As a workaround, declare the external function on namespace scope.

Rules for namespace aware code:

This concerns everything in main/* that is not "namespaced code" and any end user code that wishes to use the Qt-in-Namespace feature:

  1. All forward declarations of types, functions and objects that are in "namespaced code" must be namespaced and their use must be "namespace qualified", i.e. written as
    QT_BEGIN_NAMESPACE
    class QCheckBox;
    class QComboBox;
    QT_END_NAMESPACE
    

    This is admittedly ugly but needed. A simple using namespace QT_NAMESPACE unfortunately does not help as

    namespace QT_NAMESPACE {  }
    using namespace QT_NAMESPACE;
    class QString;
    

    will declare QString at global namespace which will be distinct from our QT_NAMESPACE::QString and cause compiler or linker errors later.

  2. A QT_BEGIN_NAMESPACE and QT_END_NAMESPACE wrapper is also needed when extending a namespace that itself lives in namespaced code. This situation typically appears when extending the QtTest namespace in auto tests.

Making code namespace aware can be given a headstart by running

find . -name '*.cpp' -o -name '*.h' -exec perl -pie 's:^class Q (.*);:QT_ADD_NAMESPACE_PREFIX($1);: {}

but it looks a bit cleaner if only QT_BEGIN_NAMESPACE and QT_END_NAMESPACE are used.

Rules for other code:

Everything else including end user code that does not need the feature and end user code that is not even aware of Qt at all does not need to be changed.

Related:

The Qt Creator Debugger can handle namespaced code as if it were "native" Qt.