We now have a current svn snapshot of libqxt in our contrib dir, and
[quassel.git] / src / contrib / libqxt-2007-10-24 / src / core / qxtpimpl.h
1 /****************************************************************************
2 **
3 ** Copyright (C) Qxt Foundation. Some rights reserved.
4 **
5 ** This file is part of the QxtCore module of the Qt eXTension library
6 **
7 ** This library is free software; you can redistribute it and/or modify it
8 ** under the terms of th Common Public License, version 1.0, as published by
9 ** IBM.
10 **
11 ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
12 ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
13 ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
14 ** FITNESS FOR A PARTICULAR PURPOSE.
15 **
16 ** You should have received a copy of the CPL along with this file.
17 ** See the LICENSE file and the cpl1.0.txt file included with the source
18 ** distribution for more information. If you did not receive a copy of the
19 ** license, contact the Qxt Foundation.
20 **
21 ** <http://libqxt.sourceforge.net>  <foundation@libqxt.org>
22 **
23 ****************************************************************************/
24 /**
25 \class QxtPimpl QxtPimpl
26 \ingroup QxtCore
27 \brief Hide private details of a class
28
29 Application code generally doesn't have to be concerned about hiding its
30 implementation details, but when writing library code it is important to
31 maintain a constant interface, both source and binary. Maintaining a constant
32 source interface is easy enough, but keeping the binary interface constant
33 means moving implementation details into a private class. The PIMPL, or
34 d-pointer, idiom is a common method of implementing this separation. QxtPimpl
35 offers a convenient way to connect the public and private sides of your class.
36
37 \section start Getting Started
38 Before you declare the public class, you need to make a forward declaration
39 of the private class. The private class must have the same name as the public
40 class, followed by the word Private. For example, a class named MyTest would
41 declare the private class with:
42 \code
43 class MyTestPrivate;
44 \endcode
45
46 \subsection pub The Public Class
47 Generally, you shouldn't keep any data members in the public class without a
48 good reason. Functions that are part of the public interface should be declared
49 in the public class, and functions that need to be available to subclasses (for
50 calling or overriding) should be in the protected section of the public class.
51 To connect the private class to the public class, include the
52 QXT_DECLARE_PRIVATE macro in the private section of the public class. In the
53 example above, the private class is connected as follows:
54 \code
55 private:
56     QXT_DECLARE_PRIVATE(MyTest);
57 \endcode
58
59 Additionally, you must include the QXT_INIT_PRIVATE macro in the public class's
60 constructor. Continuing with the MyTest example, your constructor might look
61 like this:
62 \code
63 MyTest::MyTest() {
64     // initialization
65     QXT_INIT_PRIVATE(MyTest);
66 }
67 \endcode
68
69 \subsection priv The Private Class
70 As mentioned above, data members should usually be kept in the private class.
71 This allows the memory layout of the private class to change without breaking
72 binary compatibility for the public class. Functions that exist only as
73 implementation details, or functions that need access to private data members,
74 should be implemented here.
75
76 To define the private class, inherit from the template QxtPrivate class, and
77 include the QXT_DECLARE_PUBLIC macro in its public section. The template
78 parameter should be the name of the public class. For example:
79 \code
80 class MyTestPrivate : public QxtPrivate<MyTest> {
81 public:
82     MyTestPrivate();
83     QXT_DECLARE_PUBLIC(MyTest);
84 };
85 \endcode
86
87 \section cross Accessing Private Members
88 Use the qxt_d() function (actually a function-like object) from functions in
89 the public class to access the private class. Similarly, functions in the
90 private class can invoke functions in the public class by using the qxt_p()
91 function (this one's actually a function).
92
93 For example, assume that MyTest has methods named getFoobar and doBaz(),
94 and MyTestPrivate has a member named foobar and a method named doQuux().
95 The code might resemble this example:
96 \code
97 int MyTest::getFoobar() {
98     return qxt_d().foobar;
99 }
100
101 void MyTestPrivate::doQuux() {
102     qxt_p().doBaz(foobar);
103 }
104 \endcode
105 */
106
107 #ifndef QXTPIMPL_H
108 #define QXTPIMPL_H
109
110 /*! \relates QxtPimpl
111  * Declares that a public class has a related private class.
112  *
113  * This shuold be put in the private section of the public class. The parameter is the name of the public class.
114  */
115 #define QXT_DECLARE_PRIVATE(PUB) friend class PUB##Private; QxtPrivateInterface<PUB, PUB##Private> qxt_d;
116 /*! \relates QxtPimpl
117  * Declares that a private class has a related public class.
118  *
119  * This may be put anywhere in the declaration of the private class. The parameter is the name of the public class.
120  */
121 #define QXT_DECLARE_PUBLIC(PUB) friend class PUB;
122 /*! \relates QxtPimpl
123  * Initializes resources owned by the private class.
124  *
125  * This should be called from the public class's constructor,
126  * before qxt_d() is used for the first time. The parameter is the name of the public class.
127  */
128 #define QXT_INIT_PRIVATE(PUB) qxt_d.setPublic(this);
129
130 #ifdef QXT_DOXYGEN_RUN
131 /*! \relates QxtPimpl
132  * Returns a reference to the private class.
133  *
134  * This function is only available in a class using \a QXT_DECLARE_PRIVATE.
135  */
136 QxtPrivate<PUB>& qxt_d();
137
138 /*! \relates QxtPimpl
139  * Returns a const reference to the private class.
140  *
141  * This function is only available in a class using \a QXT_DECLARE_PRIVATE.
142  * This overload will be automatically used in const functions.
143  */
144 const QxtPrivate<PUB>& qxt_d();
145
146 /*! \relates QxtPimpl
147  * Returns a reference to the public class.
148  *
149  * This function is only available in a class using \a QXT_DECLARE_PUBLIC.
150  */
151 PUB& qxt_p();
152
153 /*! \relates QxtPimpl
154  * Returns a const reference to the public class.
155  *
156  * This function is only available in a class using \a QXT_DECLARE_PUBLIC.
157  * This overload will be automatically used in const functions.
158  */
159 const PUB& qxt_p();
160 #endif
161
162 #ifndef QXT_DOXYGEN_RUN
163 template <typename PUB>
164 class QxtPrivate
165 {
166 public:
167     virtual ~QxtPrivate()
168     {}
169     inline void QXT_setPublic(PUB* pub)
170     {
171         qxt_p_ptr = pub;
172     }
173
174 protected:
175     inline PUB& qxt_p()
176     {
177         return *qxt_p_ptr;
178     }
179     inline const PUB& qxt_p() const
180     {
181         return *qxt_p_ptr;
182     }
183
184 private:
185     PUB* qxt_p_ptr;
186 };
187
188 template <typename PUB, typename PVT>
189 class QxtPrivateInterface
190 {
191     friend class QxtPrivate<PUB>;
192 public:
193     QxtPrivateInterface()
194     {
195         pvt = new PVT;
196     }
197     ~QxtPrivateInterface()
198     {
199         delete pvt;
200     }
201
202     inline void setPublic(PUB* pub)
203     {
204         pvt->QXT_setPublic(pub);
205     }
206     inline PVT& operator()()
207     {
208         return *static_cast<PVT*>(pvt);
209     }
210     inline const PVT& operator()() const
211     {
212         return *static_cast<PVT*>(pvt);
213     }
214 private:
215     QxtPrivate<PUB>* pvt;
216 };
217 #endif
218
219 #endif