1// vi:set ft=cpp: -*- Mode: C++ -*- 2 3/* SPDX-License-Identifier: GPL-2.0-only or License-Ref-kk-custom */ 4/* 5 * Copyright (C) 2013 Technische Universität Dresden. 6 * Copyright (C) 2014-2017 Kernkonzept GmbH. 7 */ 8 9#pragma once 10 11#include "type_traits" 12 13namespace cxx 14{ 15 16template< typename T > 17struct default_delete 18{ 19 default_delete() {} 20 21 template< typename U > 22 default_delete(default_delete<U> const &) {} 23 24 void operator () (T *p) const 25 { delete p; } 26}; 27 28template< typename T > 29struct default_delete<T[]> 30{ 31 default_delete() {} 32 33 void operator () (T *p) 34 { delete [] p; } 35}; 36 37template< typename T, typename C > 38struct unique_ptr_index_op {}; 39 40template< typename T, typename C > 41struct unique_ptr_index_op<T[], C> 42{ 43 typedef T &reference; 44 reference operator [] (int idx) const 45 { return static_cast<C const *>(this)->get()[idx]; } 46}; 47 48template< typename T, typename T_Del = default_delete<T> > 49class unique_ptr : public unique_ptr_index_op<T, unique_ptr<T, T_Del> > 50{ 51private: 52 struct _unspec; 53 typedef _unspec* _unspec_ptr_type; 54 55public: 56 typedef typename cxx::remove_extent<T>::type element_type; 57 typedef element_type *pointer; 58 typedef element_type &reference; 59 typedef T_Del deleter_type; 60 61 unique_ptr() : _ptr(pointer()) {} 62 63 explicit unique_ptr(pointer p) : _ptr(p) {} 64 65 unique_ptr(unique_ptr &&o) : _ptr(o.release()) {} 66 67 ~unique_ptr() { reset(); } 68 69 unique_ptr &operator = (unique_ptr &&o) 70 { 71 reset(o.release()); 72 return *this; 73 } 74 75 unique_ptr &operator = (_unspec_ptr_type) 76 { 77 reset(); 78 return *this; 79 } 80 81 element_type &operator * () const { return *get(); } 82 pointer operator -> () const { return get(); } 83 84 pointer get() const { return _ptr; } 85 86 operator _unspec_ptr_type () const 87 { return reinterpret_cast<_unspec_ptr_type>(get()); } 88 89 pointer release() 90 { 91 pointer r = _ptr; 92 _ptr = 0; 93 return r; 94 } 95 96 void reset(pointer p = pointer()) 97 { 98 if (p != get()) 99 { 100 deleter_type()(get()); 101 _ptr = p; 102 } 103 } 104 105 unique_ptr(unique_ptr const &) = delete; 106 unique_ptr &operator = (unique_ptr const &) = delete; 107 108private: 109 pointer _ptr; 110}; 111 112template< typename T > 113unique_ptr<T> 114make_unique_ptr(T *p) 115{ return unique_ptr<T>(p); } 116 117template< typename T > 118typename cxx::enable_if<cxx::is_array<T>::value, unique_ptr<T>>::type 119make_unique(unsigned long size) 120{ return cxx::unique_ptr<T>(new typename cxx::remove_extent<T>::type[size]()); } 121 122template< typename T, typename... Args > 123typename cxx::enable_if<!cxx::is_array<T>::value, unique_ptr<T>>::type 124make_unique(Args &&... args) 125{ return cxx::unique_ptr<T>(new T(cxx::forward<Args>(args)...)); } 126 127} 128