Mistake on this page?
Report an issue in GitHub or email us
NonCopyable.h
1 /* Copyright (c) 2017-2019 ARM Limited
2  * SPDX-License-Identifier: Apache-2.0
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef MBED_NONCOPYABLE_H_
18 #define MBED_NONCOPYABLE_H_
19 
20 namespace mbed {
21 
22 /** \addtogroup platform-public-api */
23 /** @{*/
24 
25 /**
26  * \defgroup platform_NonCopyable NonCopyable class
27  * @{
28  */
29 
30 /**
31  * Prevents generation of copy constructor and copy assignment operator in
32  * derived classes.
33  *
34  * @par Usage
35  *
36  * To prevent generation of copy constructor and copy assignment operator,
37  * inherit privately from the NonCopyable class.
38  *
39  * @code
40  * class Resource : NonCopyable<Resource> { };
41  *
42  * Resource r;
43  * // generates compile time error:
44  * Resource r2 = r;
45  * @endcode
46  *
47  * @par Background information
48  *
49  * Instances of polymorphic classes are not meant to be copied. The
50  * C++ standards generate a default copy constructor and copy assignment
51  * function if these functions have not been defined in the class.
52  *
53  * Consider the following example:
54  *
55  * @code
56  * // base class representing a connection
57  * struct Connection {
58  * Connection();
59  * virtual ~Connection();
60  * virtual void open() = 0;
61  * }
62  *
63  * class SerialConnection : public Connection {
64  * public:
65  * SerialConnection(Serial*);
66  *
67  * private:
68  * Serial* _serial;
69  * };
70  *
71  * Connection& get_connection() {
72  * static SerialConnection serial_connection;
73  * return serial_connection;
74  * }
75  *
76  * Connection connection = get_connection();
77  * @endcode
78  *
79  * There is a subtle bug in this code, the function get_connection returns a
80  * reference to a Connection which is captured by value instead of reference.
81  *
82  * When `get_connection` returns a reference to serial_connection it is copied into
83  * the local variable connection. The vtable and others members defined in Connection
84  * are copied, but members defined in SerialConnection are left apart. This can cause
85  * severe crashes or bugs if the virtual functions captured use members not present
86  * in the base declaration.
87  *
88  * To solve that problem, the copy constructor and assignment operator have to
89  * be defined as deleted:
90  *
91  * @code
92  * struct Connection {
93  * Connection(const Connection &) = delete;
94  * Connection &operator=(const Connection &) = delete;
95  * }
96  * @endcode
97  *
98  * Although manually defining deleted copy constructor and assignment functions
99  * works, it is not ideal. These declarations are usually easy to forget,
100  * not immediately visible, and may be obscure to uninformed programmers.
101  *
102  * Using the NonCopyable class reduces the boilerplate required and expresses
103  * the intent because class inheritance appears right after the class name
104  * declaration.
105  *
106  * @code
107  * struct Connection : private NonCopyable<Connection> {
108  * // regular declarations
109  * }
110  * @endcode
111  *
112  *
113  * @par Implementation details
114  *
115  * Using a template type prevents cases where the empty base optimization cannot
116  * be applied and therefore ensures that the cost of the NonCopyable semantic
117  * sugar is null.
118  *
119  * As an example, the empty base optimization is prohibited if one of the empty
120  * base classes is also a base type of the first nonstatic data member:
121  *
122  * @code
123  * struct A { };
124  * struct B : A {
125  * int foo;
126  * };
127  * // thanks to empty base optimization, sizeof(B) == sizeof(int)
128  *
129  * struct C : A {
130  * B b;
131  * };
132  *
133  * // empty base optimization cannot be applied here because A from C and A from
134  * // B have a different address. In that case, with the alignment
135  * // sizeof(C) == 2* sizeof(int)
136  * @endcode
137  *
138  * The solution to that problem is to templatize the empty class to make it
139  * unique to the type it is applied to:
140  *
141  * @code
142  * template<typename T>
143  * struct A<T> { };
144  * struct B : A<B> {
145  * int foo;
146  * };
147  * struct C : A<C> {
148  * B b;
149  * };
150  *
151  * // empty base optimization can be applied B and C does not refer to the same
152  * // kind of A. sizeof(C) == sizeof(B) == sizeof(int).
153  * @endcode
154  *
155  * @tparam T The type that should be made noncopyable.
156  *
157  * @note Compile time errors are disabled if you use the develop or release profile.
158  * To override this behavior and force compile time errors in all profiles,
159  * set the configuration parameter "platform.force-non-copyable-error" to true.
160  */
161 template<typename T>
162 class NonCopyable {
163 #ifndef DOXYGEN_ONLY
164 protected:
165  /**
166  * Disallow construction of NonCopyable objects from outside of its hierarchy.
167  */
168  NonCopyable() = default;
169  /**
170  * Disallow destruction of NonCopyable objects from outside of its hierarchy.
171  */
172  ~NonCopyable() = default;
173 
174 public:
175  /**
176  * Define copy constructor as deleted. Any attempt to copy construct
177  * a NonCopyable will fail at compile time.
178  */
179  NonCopyable(const NonCopyable &) = delete;
180 
181  /**
182  * Define copy assignment operator as deleted. Any attempt to copy assign
183  * a NonCopyable will fail at compile time.
184  */
185  NonCopyable &operator=(const NonCopyable &) = delete;
186 #endif
187 };
188 
189 /**@}*/
190 
191 /**@}*/
192 
193 } // namespace mbed
194 
195 #endif /* MBED_NONCOPYABLE_H_ */
Prevents generation of copy constructor and copy assignment operator in derived classes.
Definition: NonCopyable.h:162
Important Information for this Arm website

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies. If you are not happy with the use of these cookies, please review our Cookie Policy to learn how they can be disabled. By disabling cookies, some features of the site will not work.