The official mbed C/C++ SDK provides the software platform and libraries to build your applications.

Dependents:   hello SerialTestv11 SerialTestv12 Sierpinski ... 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  *
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_ */