mbed library sources. Supersedes mbed-src.

Dependents:   Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers NonCopyable.h Source File

NonCopyable.h

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