// vi:set ft=cpp: -*- Mode: C++ -*- /* SPDX-License-Identifier: GPL-2.0-only or License-Ref-kk-custom */ /* * Copyright (C) 2013 Technische Universität Dresden. * Copyright (C) 2014-2017 Kernkonzept GmbH. */ #pragma once #include "type_traits" namespace cxx { template< typename T > struct default_delete { default_delete() {} template< typename U > default_delete(default_delete const &) {} void operator () (T *p) const { delete p; } }; template< typename T > struct default_delete { default_delete() {} void operator () (T *p) { delete [] p; } }; template< typename T, typename C > struct unique_ptr_index_op {}; template< typename T, typename C > struct unique_ptr_index_op { typedef T &reference; reference operator [] (int idx) const { return static_cast(this)->get()[idx]; } }; template< typename T, typename T_Del = default_delete > class unique_ptr : public unique_ptr_index_op > { private: struct _unspec; typedef _unspec* _unspec_ptr_type; public: typedef typename cxx::remove_extent::type element_type; typedef element_type *pointer; typedef element_type &reference; typedef T_Del deleter_type; unique_ptr() : _ptr(pointer()) {} explicit unique_ptr(pointer p) : _ptr(p) {} unique_ptr(unique_ptr &&o) : _ptr(o.release()) {} ~unique_ptr() { reset(); } unique_ptr &operator = (unique_ptr &&o) { reset(o.release()); return *this; } unique_ptr &operator = (_unspec_ptr_type) { reset(); return *this; } element_type &operator * () const { return *get(); } pointer operator -> () const { return get(); } pointer get() const { return _ptr; } operator _unspec_ptr_type () const { return reinterpret_cast<_unspec_ptr_type>(get()); } pointer release() { pointer r = _ptr; _ptr = 0; return r; } void reset(pointer p = pointer()) { if (p != get()) { deleter_type()(get()); _ptr = p; } } unique_ptr(unique_ptr const &) = delete; unique_ptr &operator = (unique_ptr const &) = delete; private: pointer _ptr; }; template< typename T > unique_ptr make_unique_ptr(T *p) { return unique_ptr(p); } template< typename T > typename cxx::enable_if::value, unique_ptr>::type make_unique(unsigned long size) { return cxx::unique_ptr(new typename cxx::remove_extent::type[size]()); } template< typename T, typename... Args > typename cxx::enable_if::value, unique_ptr>::type make_unique(Args &&... args) { return cxx::unique_ptr(new T(cxx::forward(args)...)); } }