/* * smart_pointer.h version 1 - Conversion policy added. * * A simple smart pointer type implementing deep copy. * * To support conversion policy the following additions are made: * * Template select_type is added and used for selecting one of two types at * compile-time. * * Conversion policy classes allow_conversion and disallow_conversion. * * Template parameter conversion_policy, with disallow_conversion as default * argument. * * Private helper class disallow, to which the raw pointer ptr_ cannot be * converted and therefore disallowing implicit type conversion when used * as return type for the type conversion operator, se below. * * Type conversion operator, converting to either T* or disallow depending * on conversion_policy and selected by using select_type. * * Shorthand CP for conversion_policy defined. */ #ifndef SMART_POINTER_H #define SMART_POINTER_H /******************************************************************************* * TYPE SELECTION ******************************************************************************/ /* * select_type selects one of two types based upon a boolean constant. flag is a * compile-time boolean constant, and if 'true', type T1 is selected, else type * T2 is selected. * * The primary is instantiated for flag equals true, since a specialization for * flag equals false is defined. */ template struct select_type { typedef T1 result; }; template struct select_type { typedef T2 result; }; /******************************************************************************* * CONVERSION POLICY ******************************************************************************/ /* * allow_conversion allow conversion to the pointee type. */ struct allow_conversion { static const bool allow = true; }; /* * disallow_conversion does not allow conversion to the pointee type. */ struct disallow_conversion { static const bool allow = false; }; /******************************************************************************* * SMART POINTER ******************************************************************************/ template class smart_pointer { public: smart_pointer() = default; explicit smart_pointer(T* p) : ptr_{ p } {} smart_pointer(const smart_pointer& rhs) : ptr_{ copy(rhs) } {} ~smart_pointer() { delete ptr_; } smart_pointer& operator=(const smart_pointer& rhs) & { if (this != &rhs) { T* ptr{ copy(rhs) }; delete ptr_; ptr_ = ptr; } return *this; } T& operator*() const { return *ptr_; } T& operator*() { return *ptr_; } T* operator->() const { return ptr_; } T* operator->() { return ptr_; } private: // Helper class for disallowing implicit type conversion. class disallowed {}; // If implicit type conversion is allowed, 'implicit_conversion_type' // will be defined as 'pointer_type', else as 'disallowed'. using implicit_conversion_type = typename select_type::result; public: // If implicit type conversion is allowed, 'implicit_conversion_type' // will be 'pointer_type', otherwise 'implicit_conversion_type' will // be 'disallowed'. Since there is no conversion from 'pointer_type' // to 'disallowed', it will result in a compile-time error. operator implicit_conversion_type() const { return ptr_; } private: T* ptr_{ nullptr }; T* copy(const smart_pointer& sp) { return sp.ptr_ ? new T{ *sp.ptr_ } : nullptr; } }; #endif