|
16 | 16 | #ifndef MBED_NONCOPYABLE_H_
|
17 | 17 | #define MBED_NONCOPYABLE_H_
|
18 | 18 |
|
19 |
| -namespace mbed { |
| 19 | +#if (!defined(MBED_DEBUG) && (MBED_CONF_PLATFORM_FORCE_NON_COPYABLE_ERROR == 0)) |
| 20 | +#include "mbed_toolchain.h" |
| 21 | +#include "mbed_debug.h" |
| 22 | +#endif |
| 23 | + |
| 24 | +namespace mbed { |
20 | 25 |
|
21 | 26 | /**
|
22 |
| - * Inheriting from this class autogeneration of copy construction and copy |
23 |
| - * assignement operations. |
24 |
| - * |
25 |
| - * Classes which are not value type should inherit privately from this class |
| 27 | + * Inheriting from this class autogeneration of copy construction and copy |
| 28 | + * assignement operations. |
| 29 | + * |
| 30 | + * Classes which are not value type should inherit privately from this class |
26 | 31 | * to avoid generation of invalid copy constructor or copy assignement operator
|
27 |
| - * which can lead to unoticeable programming errors. |
28 |
| - * |
29 |
| - * As an example consider the following signature: |
30 |
| - * |
| 32 | + * which can lead to unoticeable programming errors. |
| 33 | + * |
| 34 | + * As an example consider the following signature: |
| 35 | + * |
31 | 36 | * @code
|
32 |
| - * class Resource; |
| 37 | + * class Resource; |
33 | 38 | *
|
34 |
| - * class Foo { |
35 |
| - * public: |
| 39 | + * class Foo { |
| 40 | + * public: |
36 | 41 | * Foo() : _resource(new Resource()) { }
|
37 |
| - * ~Foo() { delete _resource; } |
| 42 | + * ~Foo() { delete _resource; } |
38 | 43 | * private:
|
39 | 44 | * Resource* _resource;
|
40 | 45 | * }
|
41 |
| - * |
| 46 | + * |
42 | 47 | * Foo get_foo();
|
43 |
| - * |
| 48 | + * |
44 | 49 | * Foo foo = get_foo();
|
45 |
| - * @endcode |
46 |
| - * |
47 |
| - * There is a bug in this function, it returns a temporary value which will be |
48 |
| - * byte copied into foo then destroyed. Unfortunately, internaly the Foo class |
49 |
| - * manage a pointer to a Resource object. This pointer will be released when the |
50 |
| - * temporary is destroyed and foo will manage a pointer to an already released |
| 50 | + * @endcode |
| 51 | + * |
| 52 | + * There is a bug in this function, it returns a temporary value which will be |
| 53 | + * byte copied into foo then destroyed. Unfortunately, internaly the Foo class |
| 54 | + * manage a pointer to a Resource object. This pointer will be released when the |
| 55 | + * temporary is destroyed and foo will manage a pointer to an already released |
51 | 56 | * Resource.
|
52 |
| - * |
53 |
| - * Two issues has to be fixed in the example above: |
54 |
| - * - Function signature has to be changed to reflect the fact that Foo |
55 |
| - * instances cannot be copied. In that case accessor should return a |
56 |
| - * reference to give access to objects already existing and managed. |
| 57 | + * |
| 58 | + * Two issues has to be fixed in the example above: |
| 59 | + * - Function signature has to be changed to reflect the fact that Foo |
| 60 | + * instances cannot be copied. In that case accessor should return a |
| 61 | + * reference to give access to objects already existing and managed. |
57 | 62 | * Generator on the other hand should return a pointer to the created object.
|
58 |
| - * |
59 |
| - * @code |
| 63 | + * |
| 64 | + * @code |
60 | 65 | * // return a reference to an already managed Foo instance
|
61 |
| - * Foo& get_foo(); |
| 66 | + * Foo& get_foo(); |
62 | 67 | * Foo& foo = get_foo();
|
63 |
| - * |
| 68 | + * |
64 | 69 | * // create a new Foo instance
|
65 | 70 | * Foo* make_foo();
|
66 | 71 | * Foo* m = make_foo();
|
67 | 72 | * @endcode
|
68 |
| - * |
69 |
| - * - Copy constructor and copy assignement operator has to be made private |
70 |
| - * in the Foo class. It prevents unwanted copy of Foo objects. This can be |
71 |
| - * done by declaring copy constructor and copy assignement in the private |
| 73 | + * |
| 74 | + * - Copy constructor and copy assignement operator has to be made private |
| 75 | + * in the Foo class. It prevents unwanted copy of Foo objects. This can be |
| 76 | + * done by declaring copy constructor and copy assignement in the private |
72 | 77 | * section of the Foo class.
|
73 |
| - * |
74 |
| - * @code |
75 |
| - * class Foo { |
76 |
| - * public: |
| 78 | + * |
| 79 | + * @code |
| 80 | + * class Foo { |
| 81 | + * public: |
77 | 82 | * Foo() : _resource(new Resource()) { }
|
78 |
| - * ~Foo() { delete _resource; } |
| 83 | + * ~Foo() { delete _resource; } |
79 | 84 | * private:
|
80 |
| - * // disallow copy operations |
| 85 | + * // disallow copy operations |
81 | 86 | * Foo(const Foo&);
|
82 | 87 | * Foo& operator=(const Foo&);
|
83 |
| - * // data members |
| 88 | + * // data members |
84 | 89 | * Resource* _resource;
|
85 | 90 | * }
|
86 | 91 | * @endcode
|
87 |
| - * |
88 |
| - * Another solution is to inherit privately from the NonCopyable class. |
89 |
| - * It reduces the boiler plate needed to avoid copy operations but more |
| 92 | + * |
| 93 | + * Another solution is to inherit privately from the NonCopyable class. |
| 94 | + * It reduces the boiler plate needed to avoid copy operations but more |
90 | 95 | * importantly it clarifies the programer intent and the object semantic.
|
91 | 96 | *
|
92 |
| - * class Foo : private NonCopyable<Foo> { |
93 |
| - * public: |
| 97 | + * class Foo : private NonCopyable<Foo> { |
| 98 | + * public: |
94 | 99 | * Foo() : _resource(new Resource()) { }
|
95 |
| - * ~Foo() { delete _resource; } |
| 100 | + * ~Foo() { delete _resource; } |
96 | 101 | * private:
|
97 | 102 | * Resource* _resource;
|
98 | 103 | * }
|
99 |
| - * |
100 |
| - * @tparam T The type that should be made non copyable. It prevent cases where |
101 |
| - * the empty base optimization cannot be applied and therefore ensure that the |
102 |
| - * cost of this semantic sugar is null. |
103 |
| - * |
104 |
| - * As an example, the empty base optimization is prohibited if one of the empty |
105 |
| - * base class is also a base type of the first non static data member: |
106 |
| - * |
107 |
| - * @code |
| 104 | + * |
| 105 | + * @tparam T The type that should be made non copyable. It prevent cases where |
| 106 | + * the empty base optimization cannot be applied and therefore ensure that the |
| 107 | + * cost of this semantic sugar is null. |
| 108 | + * |
| 109 | + * As an example, the empty base optimization is prohibited if one of the empty |
| 110 | + * base class is also a base type of the first non static data member: |
| 111 | + * |
| 112 | + * @code |
108 | 113 | * struct A { };
|
109 |
| - * struct B : A { |
| 114 | + * struct B : A { |
110 | 115 | * int foo;
|
111 | 116 | * };
|
112 | 117 | * // thanks to empty base optimization, sizeof(B) == sizeof(int)
|
113 |
| - * |
114 |
| - * struct C : A { |
| 118 | + * |
| 119 | + * struct C : A { |
115 | 120 | * B b;
|
116 | 121 | * };
|
117 |
| - * |
| 122 | + * |
118 | 123 | * // empty base optimization cannot be applied here because A from C and A from
|
119 |
| - * // B shall have a different address. In that case, with the alignement |
| 124 | + * // B shall have a different address. In that case, with the alignement |
120 | 125 | * // sizeof(C) == 2* sizeof(int)
|
121 | 126 | * @endcode
|
122 |
| - * |
123 |
| - * The solution to that problem is to templatize the empty class to makes it |
124 |
| - * unique to the type it is applied to: |
125 |
| - * |
126 |
| - * @code |
| 127 | + * |
| 128 | + * The solution to that problem is to templatize the empty class to makes it |
| 129 | + * unique to the type it is applied to: |
| 130 | + * |
| 131 | + * @code |
127 | 132 | * template<typename T>
|
128 | 133 | * struct A<T> { };
|
129 |
| - * struct B : A<B> { |
| 134 | + * struct B : A<B> { |
130 | 135 | * int foo;
|
131 | 136 | * };
|
132 |
| - * struct C : A<C> { |
| 137 | + * struct C : A<C> { |
133 | 138 | * B b;
|
134 | 139 | * };
|
135 |
| - * |
136 |
| - * // empty base optimization can be applied B and C does not refer to the same |
| 140 | + * |
| 141 | + * // empty base optimization can be applied B and C does not refer to the same |
137 | 142 | * // kind of A. sizeof(C) == sizeof(B) == sizeof(int).
|
138 | 143 | * @endcode
|
| 144 | + * |
| 145 | + * @note Compile time errors are disabled if the develop or the release profile |
| 146 | + * is used. To override this behavior and force compile time errors in all profile |
| 147 | + * set the configuration parameter "platform.force-non-copyable-error" to true. |
139 | 148 | */
|
140 | 149 | template<typename T>
|
141 |
| -class NonCopyable { |
| 150 | +class NonCopyable { |
142 | 151 | protected:
|
143 |
| - /** |
| 152 | + /** |
144 | 153 | * Disalow construction of NonCopyable objects from outside of its hierarchy.
|
145 | 154 | */
|
146 | 155 | NonCopyable() { }
|
147 |
| - /** |
| 156 | + /** |
148 | 157 | * Disalow destruction of NonCopyable objects from outside of its hierarchy.
|
149 | 158 | */
|
150 | 159 | ~NonCopyable() { }
|
151 | 160 |
|
152 |
| -private: |
| 161 | +#if (!defined(MBED_DEBUG) && (MBED_CONF_PLATFORM_FORCE_NON_COPYABLE_ERROR == 0)) |
| 162 | + /** |
| 163 | + * NonCopyable copy constructor. |
| 164 | + * |
| 165 | + * A compile time warning is issued when this function is used and a runtime |
| 166 | + * warning is printed when the copy construction of the non copyable happens. |
| 167 | + * |
| 168 | + * If you see this warning, your code is probably doing something unspecified. |
| 169 | + * Copy of non copyable resources can lead to resource leak and random error. |
| 170 | + */ |
| 171 | + MBED_DEPRECATED("Invalid copy construction of a NonCopyable resource.") |
| 172 | + NonCopyable(const NonCopyable&) |
| 173 | + { |
| 174 | + debug("Invalid copy construction of a NonCopyable resource: %s\r\n", MBED_PRETTY_FUNCTION); |
| 175 | + } |
| 176 | + |
| 177 | + /** |
| 178 | + * NonCopyable copy assignment operator. |
| 179 | + * |
| 180 | + * A compile time warning is issued when this function is used and a runtime |
| 181 | + * warning is printed when the copy construction of the non copyable happens. |
| 182 | + * |
| 183 | + * If you see this warning, your code is probably doing something unspecified. |
| 184 | + * Copy of non copyable resources can lead to resource leak and random error. |
| 185 | + */ |
| 186 | + MBED_DEPRECATED("Invalid copy assignment of a NonCopyable resource.") |
| 187 | + NonCopyable& operator=(const NonCopyable&) |
| 188 | + { |
| 189 | + debug("Invalid copy assignment of a NonCopyable resource: %s\r\n", MBED_PRETTY_FUNCTION); |
| 190 | + return *this; |
| 191 | + } |
| 192 | + |
| 193 | +#else |
| 194 | +private: |
153 | 195 | /**
|
154 |
| - * Declare copy constructor as private, any attempt to copy construct |
| 196 | + * Declare copy constructor as private, any attempt to copy construct |
155 | 197 | * a NonCopyable will fail at compile time.
|
156 | 198 | */
|
157 | 199 | NonCopyable(const NonCopyable&);
|
158 | 200 |
|
159 | 201 | /**
|
160 |
| - * Declare copy assignement operator as private, any attempt to copy assign |
| 202 | + * Declare copy assignement operator as private, any attempt to copy assign |
161 | 203 | * a NonCopyable will fail at compile time.
|
162 | 204 | */
|
163 | 205 | NonCopyable& operator=(const NonCopyable&);
|
| 206 | +#endif |
164 | 207 | };
|
165 | 208 |
|
166 |
| -} // namespace mbed |
| 209 | +} // namespace mbed |
167 | 210 |
|
168 | 211 | #endif /* MBED_NONCOPYABLE_H_ */
|
0 commit comments