move tests to dptr
[web/konrad/chester.git] / dptr.h
1 //d-ptr header
2 //
3 // (c) Konrad Rosenbaum, 2010
4 // protected under the GNU LGPL v3 or at your option any newer
5
6 #ifndef DPTR_H
7 #define DPTR_H
8
9 /** \page dptr Automatic d-Pointers
10 to be written
11
12 \see dptr.h
13 */
14
15 /** \file "dptr.h"
16 Automatic d-Pointers Header File
17
18 Please see \ref dptr "Automatic d-Pointers"
19 for a tutorial.
20 */
21
22 /** \brief Expands to the fully qualified name of the d-pointer class.
23 \param Class the fully qualified name of the class the d-pointer was declared in.*/
24 #define DPTR_CLASS_NAME(Class) Class::Private
25 ///Expands to the local name of d-pointer classes (Private).
26 #define DPTR_NAME Private
27 ///Expands to the local name of the d-pointer wrapper class (DPrivate).
28 #define DPTR_WRAPPER_NAME DPrivate
29
30 /** \brief Declares a smart shared or non-shared d-pointer, to be used inside class declaration.
31
32 It also declares the internal nested classes DPrivate and Private - Private is the actual d-pointer class, while DPrivate is a wrapper that automatically allocates, copies and deallocates the d-pointer.
33
34 The wrapper DPointer class contains these methods:
35    - constructor, copy constructor for creating instances of Private
36     - used by automatic and explicit constructors of the containing class
37    - destructor for deallocation of Private
38     - used by the destructor of the containing class
39    - assignment operator to copy the content of Private
40     - used by the assignment operator of the containing class
41    - pointer operator to actually access the Private data
42
43 You can use DEFINE_DPTR to define the necessary methods for a non-shared d-pointer or DEFINE_SHARED_DPTR if you want to share d-pointer data between instances of the containing class. It is recommended that non-shared d-pointer classes (Private) are derived from DPtr and the shared variants be derived from SharedDPtr.
44
45 The d-pointer class Private is only forward declared, you have to fully declare and implement it in the code where you are using it, i.e. where you are implementing the containing class.
46
47 \param dp name of the d-pointer*/
48 #define DECLARE_DPTR(dp) \
49  private:\
50  class Private; \
51  class DPrivate{\
52   public:DPrivate();DPrivate(const DPrivate&);~DPrivate();\
53   DPrivate&operator=(const DPrivate&);\
54   const Private*operator->()const{return d;}\
55   Private*operator->(){return d;}\
56   DPrivate clone()const;\
57   private:Private*d;\
58  }; \
59  DPrivate dp;
60
61  /** \brief Alias for DECLARE_DPTR for convenience.
62
63 \param dp name of the d-pointer*/
64 #define DECLARE_SHARED_DPTR(dp) DECLARE_DPTR(dp)
65
66 /** \brief Base class of non-shared d-pointers.
67
68 Use in conjunction with DECLARE_DPTR and DEFINE_DPTR */
69 class DPtr
70 {
71         public:
72                 ///instantiates a non-shared d-pointer
73                 DPtr(){}
74                 ///deletes a non-shared d-pointer
75                 virtual ~DPtr(){}
76 };
77
78 /** \brief Creates definitions for methods of the non-shared d-pointer wrapper. 
79
80 This variant is not shared between instances of the containing class.
81
82 To be used in implementation where the actual d-pointer class is implemented.
83
84 \param Class the base class within which the d-pointer was declared*/
85 #define DEFINE_DPTR(Class) \
86  Class::DPrivate::DPrivate(){d=new Class::Private;}\
87  Class::DPrivate::DPrivate(const Class::DPrivate&dp){d=new Class::Private(*(dp.d));}\
88  Class::DPrivate::~DPrivate(){delete d;}\
89  Class::DPrivate Class::DPrivate::clone()const{DPrivate r;*(r.d)=*d;return r;}\
90  Class::DPrivate& Class::DPrivate::operator=(const Class::DPrivate&dp)\
91  {*d=*(dp.d);return *this;}
92
93 /** \brief Base class of shared d-pointers.
94
95 Use in conjunction with DECLARE_SHARED_DPTR and DEFINE_SHARED_DPTR */
96 class SharedDPtr
97 {
98         private:
99                 int cnt;
100         public:
101                 ///instantiates a shared d-pointer
102                 SharedDPtr(){cnt=1;}
103                 ///deletes a shared d-pointer
104                 virtual ~SharedDPtr(){}
105                 ///called by the wrapper to attach to a new instance
106                 virtual void attach(){cnt++;}
107                 ///called by the wrapper to detach from an instance
108                 virtual void detach(){cnt--;if(cnt==0)delete this;}
109 };
110
111 /** \brief Defines the methods of the shared d-pointer wrapper.
112
113 This implements the shared version of the d-pointer wrapper.
114 To be used in implementation where the actual d-pointer class is implemented.
115
116 \param Class the base class within which the d-pointer was declared*/
117 #define DEFINE_SHARED_DPTR(Class) \
118  Class::DPrivate::DPrivate(){d=new Class::Private;}\
119  Class::DPrivate::DPrivate(const DPrivate&dp){d=dp.d;d->attach();}\
120  Class::DPrivate::~DPrivate(){d->detach();}\
121  Class::DPrivate Class::DPrivate::clone()const{DPrivate r;*(r.d)=*d;return r;}\
122  Class::DPrivate& Class::DPrivate::operator=(const DPrivate&dp)\
123  {d->detach();d=dp.d;d->attach();return *this;}
124
125
126 #endif