Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
NonCopyable.h
00001 /* Copyright (c) 2017 ARM Limited 00002 * 00003 * Licensed under the Apache License, Version 2.0 (the "License"); 00004 * you may not use this file except in compliance with the License. 00005 * You may obtain a copy of the License at 00006 * 00007 * http://www.apache.org/licenses/LICENSE-2.0 00008 * 00009 * Unless required by applicable law or agreed to in writing, software 00010 * distributed under the License is distributed on an "AS IS" BASIS, 00011 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00012 * See the License for the specific language governing permissions and 00013 * limitations under the License. 00014 */ 00015 00016 #ifndef MBED_NONCOPYABLE_H_ 00017 #define MBED_NONCOPYABLE_H_ 00018 00019 #if (!defined(MBED_DEBUG) && (MBED_CONF_PLATFORM_FORCE_NON_COPYABLE_ERROR == 0)) 00020 #include "mbed_toolchain.h" 00021 #include "mbed_debug.h" 00022 #endif 00023 00024 namespace mbed { 00025 00026 /** \addtogroup platform */ 00027 /** @{*/ 00028 /** 00029 * \defgroup platform_NonCopyable NonCopyable class 00030 * @{ 00031 */ 00032 00033 /** 00034 * Prevents generation of copy constructor and copy assignment operator in 00035 * derived classes. 00036 * 00037 * @par Usage 00038 * 00039 * To prevent generation of copy constructor and copy assignment operator, 00040 * inherit privately from the NonCopyable class. 00041 * 00042 * @code 00043 * class Resource : NonCopyable<Resource> { }; 00044 * 00045 * Resource r; 00046 * // generates compile time error: 00047 * Resource r2 = r; 00048 * @endcode 00049 * 00050 * @par Background information 00051 * 00052 * Instances of polymorphic classes are not meant to be copied. The 00053 * C++ standards generate a default copy constructor and copy assignment 00054 * function if these functions have not been defined in the class. 00055 * 00056 * Consider the following example: 00057 * 00058 * @code 00059 * // base class representing a connection 00060 * struct Connection { 00061 * Connection(); 00062 * virtual ~Connection(); 00063 * virtual void open() = 0; 00064 * } 00065 * 00066 * class SerialConnection : public Connection { 00067 * public: 00068 * SerialConnection(Serial*); 00069 * 00070 * private: 00071 * Serial* _serial; 00072 * }; 00073 * 00074 * Connection& get_connection() { 00075 * static SerialConnection serial_connection; 00076 * return serial_connection; 00077 * } 00078 * 00079 * Connection connection = get_connection(); 00080 * @endcode 00081 * 00082 * There is a subtle bug in this code, the function get_connection returns a 00083 * reference to a Connection which is captured by value instead of reference. 00084 * 00085 * When `get_connection` returns a reference to serial_connection it is copied into 00086 * the local variable connection. The vtable and others members defined in Connection 00087 * are copied, but members defined in SerialConnection are left apart. This can cause 00088 * severe crashes or bugs if the virtual functions captured use members not present 00089 * in the base declaration. 00090 * 00091 * To solve that problem, the copy constructor and assignment operator have to 00092 * be declared (but don't need to be defined) in the private section of the 00093 * Connection class: 00094 * 00095 * @code 00096 * struct Connection { 00097 * private: 00098 * Connection(const Connection&); 00099 * Connection& operator=(const Connection&); 00100 * } 00101 * @endcode 00102 * 00103 * Although manually declaring private copy constructor and assignment functions 00104 * works, it is not ideal. These declarations are usually easy to forget, 00105 * not immediately visible, and may be obscure to uninformed programmers. 00106 * 00107 * Using the NonCopyable class reduces the boilerplate required and expresses 00108 * the intent because class inheritance appears right after the class name 00109 * declaration. 00110 * 00111 * @code 00112 * struct Connection : private NonCopyable<Connection> { 00113 * // regular declarations 00114 * } 00115 * @endcode 00116 * 00117 * 00118 * @par Implementation details 00119 * 00120 * Using a template type prevents cases where the empty base optimization cannot 00121 * be applied and therefore ensures that the cost of the NonCopyable semantic 00122 * sugar is null. 00123 * 00124 * As an example, the empty base optimization is prohibited if one of the empty 00125 * base classes is also a base type of the first nonstatic data member: 00126 * 00127 * @code 00128 * struct A { }; 00129 * struct B : A { 00130 * int foo; 00131 * }; 00132 * // thanks to empty base optimization, sizeof(B) == sizeof(int) 00133 * 00134 * struct C : A { 00135 * B b; 00136 * }; 00137 * 00138 * // empty base optimization cannot be applied here because A from C and A from 00139 * // B have a different address. In that case, with the alignment 00140 * // sizeof(C) == 2* sizeof(int) 00141 * @endcode 00142 * 00143 * The solution to that problem is to templatize the empty class to make it 00144 * unique to the type it is applied to: 00145 * 00146 * @code 00147 * template<typename T> 00148 * struct A<T> { }; 00149 * struct B : A<B> { 00150 * int foo; 00151 * }; 00152 * struct C : A<C> { 00153 * B b; 00154 * }; 00155 * 00156 * // empty base optimization can be applied B and C does not refer to the same 00157 * // kind of A. sizeof(C) == sizeof(B) == sizeof(int). 00158 * @endcode 00159 * 00160 * @tparam T The type that should be made noncopyable. 00161 * 00162 * @note Compile time errors are disabled if you use the develop or release profile. 00163 * To override this behavior and force compile time errors in all profiles, 00164 * set the configuration parameter "platform.force-non-copyable-error" to true. 00165 */ 00166 template<typename T> 00167 class NonCopyable { 00168 #ifndef DOXYGEN_ONLY 00169 protected: 00170 /** 00171 * Disallow construction of NonCopyable objects from outside of its hierarchy. 00172 */ 00173 NonCopyable() { } 00174 /** 00175 * Disallow destruction of NonCopyable objects from outside of its hierarchy. 00176 */ 00177 ~NonCopyable() { } 00178 00179 #if (!defined(MBED_DEBUG) && (MBED_CONF_PLATFORM_FORCE_NON_COPYABLE_ERROR == 0)) 00180 /** 00181 * NonCopyable copy constructor. 00182 * 00183 * A compile time warning is issued when this function is used, and a runtime 00184 * warning is printed when the copy construction of the noncopyable happens. 00185 * 00186 * If you see this warning, your code is probably doing something unspecified. 00187 * Copying of noncopyable resources can lead to resource leak and random error. 00188 */ 00189 MBED_DEPRECATED("Invalid copy construction of a NonCopyable resource.") 00190 NonCopyable(const NonCopyable &) 00191 { 00192 debug("Invalid copy construction of a NonCopyable resource: %s\r\n", MBED_PRETTY_FUNCTION); 00193 } 00194 00195 /** 00196 * NonCopyable copy assignment operator. 00197 * 00198 * A compile time warning is issued when this function is used, and a runtime 00199 * warning is printed when the copy construction of the noncopyable happens. 00200 * 00201 * If you see this warning, your code is probably doing something unspecified. 00202 * Copying of noncopyable resources can lead to resource leak and random error. 00203 */ 00204 MBED_DEPRECATED("Invalid copy assignment of a NonCopyable resource.") 00205 NonCopyable &operator=(const NonCopyable &) 00206 { 00207 debug("Invalid copy assignment of a NonCopyable resource: %s\r\n", MBED_PRETTY_FUNCTION); 00208 return *this; 00209 } 00210 00211 #else 00212 private: 00213 /** 00214 * Declare copy constructor as private. Any attempt to copy construct 00215 * a NonCopyable will fail at compile time. 00216 */ 00217 NonCopyable(const NonCopyable &); 00218 00219 /** 00220 * Declare copy assignment operator as private. Any attempt to copy assign 00221 * a NonCopyable will fail at compile time. 00222 */ 00223 NonCopyable &operator=(const NonCopyable &); 00224 #endif 00225 #endif 00226 }; 00227 00228 /**@}*/ 00229 00230 /**@}*/ 00231 00232 } // namespace mbed 00233 00234 #endif /* MBED_NONCOPYABLE_H_ */
Generated on Tue Jul 12 2022 20:52:52 by
1.7.2