Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers NonCopyable.h Source File

NonCopyable.h

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