/* * Copyright (c) 2016 - present Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. */ #pragma once #include #include INFER_NAMESPACE_STD_BEGIN // IMPORTANT // There is specialization of unique_ptr below and it's mosly copy paste. // When changing model, remember to change it for specialization as well! template > struct unique_ptr { // use SFINAE to determine whether _Del::pointer exists class _Pointer { template static typename _Up::pointer __test(typename _Up::pointer*); template static _Tp* __test(...); typedef typename remove_reference<_Dp>::type _Del; public: typedef decltype(__test<_Del>(0)) type; }; public: typedef typename _Pointer::type pointer; typedef _Tp element_type; typedef _Dp deleter_type; private: /* std::unique_ptr in infer is translated as T* Look at model of std::shared_ptr for more details */ // translate shared_ptr as type 'pointer' friend class infer_traits::TranslateAsType; /// type of 'this' in unique_ptr as seen by infer typedef const void** infer_unique_ptr_t; // use it to avoid compilation errors and make infer analyzer happy #define __cast_to_infer_ptr(self) ((infer_unique_ptr_t)self) // provide overload for volatile void* to accomodate for situation when // T is volatile ('volatile int' for example). 'void*' and 'nullptr_t' // overloads are to avoid 'call to model_set is ambiguous' compilation errors static void model_set(infer_unique_ptr_t self, nullptr_t value) noexcept { *self = value; } static void model_set(infer_unique_ptr_t self, const void* value) noexcept { *self = value; } static void model_set(infer_unique_ptr_t self, volatile void* value) noexcept { *self = const_cast(value); } static void model_set(infer_unique_ptr_t self, void* value) noexcept { *self = const_cast(value); } // in case 'pointer' type is not type pointer, enable catch all overload of // `model_set` to prevent compliation issues static void model_set(...) noexcept { /* no model for this overload */ } static void model_move(infer_unique_ptr_t self, infer_unique_ptr_t other) noexcept { *self = *other; model_set(other, nullptr); } static void model_swap(infer_unique_ptr_t infer_self, infer_unique_ptr_t infer_other) noexcept { const void* t = *infer_self; *infer_self = *infer_other; *infer_other = t; } pointer __ignore__; // used to keep sizeof(unique_ptr) same as in standard public: template unique_ptr(const std__unique_ptr& u) {} constexpr unique_ptr() noexcept { model_set(__cast_to_infer_ptr(this), nullptr); } constexpr unique_ptr(nullptr_t) noexcept : unique_ptr<_Tp, _Dp>() {} explicit unique_ptr(pointer ptr) noexcept { model_set(__cast_to_infer_ptr(this), ptr); } unique_ptr(pointer ptr, typename conditional< is_reference::value, deleter_type, typename add_lvalue_reference::type>::type __d) noexcept : unique_ptr<_Tp, _Dp>(ptr) {} unique_ptr(pointer ptr, typename remove_reference::type&& __d) noexcept : unique_ptr<_Tp, _Dp>(ptr) {} unique_ptr(unique_ptr&& u) noexcept { model_move(__cast_to_infer_ptr(this), __cast_to_infer_ptr(&u)); } template ::value && is_convertible::pointer, pointer>::value && is_convertible<_Ep, deleter_type>::value && (!is_reference::value || is_same::value)>::type> unique_ptr(unique_ptr<_Up, _Ep>&& u) noexcept { model_move(__cast_to_infer_ptr(this), __cast_to_infer_ptr(&u)); } template < class _Up, typename = typename enable_if::value>::type> unique_ptr(auto_ptr<_Up>&& __p) noexcept; ~unique_ptr() { reset(); } unique_ptr& operator=(unique_ptr&& __u) noexcept { model_move(__cast_to_infer_ptr(this), __cast_to_infer_ptr(&__u)); return *this; } template ::value && is_convertible::pointer, pointer>::value && is_assignable::value>::type> unique_ptr& operator=(unique_ptr<_Up, _Ep>&& __u) noexcept { model_move(__cast_to_infer_ptr(this), __cast_to_infer_ptr(&__u)); return *this; } unique_ptr& operator=(nullptr_t) noexcept { reset(); return *this; } typename add_lvalue_reference<_Tp>::type operator*() const INFER_MODEL_AS_DEREF_FIRST_ARG; pointer operator->() const INFER_MODEL_AS_DEREF_FIRST_ARG; pointer get() const INFER_MODEL_AS_DEREF_FIRST_ARG; typedef typename remove_reference::type& _Dp_reference; typedef const typename remove_reference::type& _Dp_const_reference; _Dp_const_reference get_deleter() const {} _Dp_reference get_deleter() {} explicit operator bool() const { return !!(bool)(*__cast_to_infer_ptr(this)); } pointer release() INFER_MODEL_AS_DEREF_FIRST_ARG; void reset(pointer p = nullptr) { model_set(__cast_to_infer_ptr(this), p); } void swap(unique_ptr& u) { model_swap(__cast_to_infer_ptr(this), __cast_to_infer_ptr(&u)); } }; template struct unique_ptr<_Tp[], _Dp> { // use SFINAE to determine whether _Del::pointer exists class _Pointer { template static typename _Up::pointer __test(typename _Up::pointer*); template static _Tp* __test(...); typedef typename remove_reference<_Dp>::type _Del; public: typedef decltype(__test<_Del>(0)) type; }; public: typedef typename _Pointer::type pointer; typedef _Tp element_type; typedef _Dp deleter_type; private: // translate shared_ptr as type pointer friend class infer_traits::TranslateAsType; /// type of 'this' in unique_ptr as seen by infer typedef const void** infer_unique_ptr_t; // use it to avoid compilation errors and make infer analyzer happy #define __cast_to_infer_ptr(self) ((infer_unique_ptr_t)self) static void model_set(infer_unique_ptr_t self, const void* value) noexcept { *self = value; } // in case 'pointer' type is not type pointer, enable catch all overload of // `model_set` to prevent compliation issues static void model_set(...) noexcept { /* no model for this overload */ } static void model_move(infer_unique_ptr_t self, infer_unique_ptr_t other) noexcept { *self = *other; model_set(other, nullptr); } static void model_swap(infer_unique_ptr_t infer_self, infer_unique_ptr_t infer_other) noexcept { const void* t = *infer_self; *infer_self = *infer_other; *infer_other = t; } pointer __ignore__; // used to keep sizeof(unique_ptr) same as in standard public: constexpr unique_ptr() noexcept { model_set(__cast_to_infer_ptr(this), nullptr); } constexpr unique_ptr(nullptr_t) noexcept : unique_ptr() {} explicit unique_ptr(pointer ptr) noexcept { model_set(__cast_to_infer_ptr(this), ptr); } unique_ptr( pointer ptr, typename conditional< is_reference::value, deleter_type, typename add_lvalue_reference::type>::type __d) noexcept : unique_ptr(ptr) {} unique_ptr(pointer ptr, typename remove_reference::type&& __d) noexcept : unique_ptr(ptr) {} unique_ptr(unique_ptr&& u) noexcept { model_move(__cast_to_infer_ptr(this), __cast_to_infer_ptr(&u)); } template ::value && is_convertible::pointer, pointer>::value && is_convertible<_Ep, deleter_type>::value && (!is_reference::value || is_same::value)>::type> unique_ptr(unique_ptr<_Up, _Ep>&& u) noexcept { model_move(__cast_to_infer_ptr(this), __cast_to_infer_ptr(&u)); } template < class _Up, typename = typename enable_if::value>::type> unique_ptr(auto_ptr<_Up>&& __p) noexcept; ~unique_ptr() { reset(); } unique_ptr& operator=(unique_ptr&& __u) noexcept { model_move(__cast_to_infer_ptr(this), __cast_to_infer_ptr(&__u)); return *this; } template ::value && is_convertible::pointer, pointer>::value && is_assignable::value>::type> unique_ptr& operator=(unique_ptr<_Up, _Ep>&& __u) noexcept { model_move(__cast_to_infer_ptr(this), __cast_to_infer_ptr(&__u)); return *this; } unique_ptr& operator=(nullptr_t) noexcept { reset(); return *this; } typename add_lvalue_reference<_Tp>::type operator[](size_t i) const INFER_MODEL_AS_DEREF_FIRST_ARG; pointer get() const INFER_MODEL_AS_DEREF_FIRST_ARG; typedef typename remove_reference::type& _Dp_reference; typedef const typename remove_reference::type& _Dp_const_reference; _Dp_const_reference get_deleter() const {} _Dp_reference get_deleter() {} explicit operator bool() const { return !!(bool)(*__cast_to_infer_ptr(this)); } pointer release() INFER_MODEL_AS_DEREF_FIRST_ARG; void reset(pointer p = nullptr) { model_set(__cast_to_infer_ptr(this), p); } void swap(unique_ptr& u) { model_swap(__cast_to_infer_ptr(this), __cast_to_infer_ptr(&u)); } }; template inline bool operator==(const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) { return __x.get() == __y.get(); } template inline bool operator!=(const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) { return !(__x == __y); } template inline bool operator<(const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) { /*typedef typename unique_ptr<_T1, _D1>::pointer _P1; typedef typename unique_ptr<_T2, _D2>::pointer _P2; typedef typename common_type<_P1, _P2>::type _Vp; return less<_Vp>()(__x.get(), __y.get());*/ } template inline bool operator>(const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) { return __y < __x; } template inline bool operator<=(const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) { return !(__y < __x); } template inline bool operator>=(const unique_ptr<_T1, _D1>& __x, const unique_ptr<_T2, _D2>& __y) { return !(__x < __y); } template inline bool operator==(const unique_ptr<_T1, _D1>& __x, nullptr_t) { return !__x; } template inline bool operator==(nullptr_t, const unique_ptr<_T1, _D1>& __x) { return !__x; } template inline bool operator!=(const unique_ptr<_T1, _D1>& __x, nullptr_t) { return static_cast(__x); } template inline bool operator!=(nullptr_t, const unique_ptr<_T1, _D1>& __x) { return static_cast(__x); } template inline bool operator<(const unique_ptr<_T1, _D1>& __x, nullptr_t) { /*typedef typename unique_ptr<_T1, _D1>::pointer _P1; return less<_P1>()(__x.get(), nullptr);*/ } template inline bool operator<(nullptr_t, const unique_ptr<_T1, _D1>& __x) { /*typedef typename unique_ptr<_T1, _D1>::pointer _P1; return less<_P1>()(nullptr, __x.get());*/ } template inline bool operator>(const unique_ptr<_T1, _D1>& __x, nullptr_t) { return nullptr < __x; } template inline bool operator>(nullptr_t, const unique_ptr<_T1, _D1>& __x) { return __x < nullptr; } template inline bool operator<=(const unique_ptr<_T1, _D1>& __x, nullptr_t) { return !(nullptr < __x); } template inline bool operator<=(nullptr_t, const unique_ptr<_T1, _D1>& __x) { return !(__x < nullptr); } template inline bool operator>=(const unique_ptr<_T1, _D1>& __x, nullptr_t) { return !(__x < nullptr); } template inline bool operator>=(nullptr_t, const unique_ptr<_T1, _D1>& __x) { return !(nullptr < __x); } template struct hash> : public hash> { size_t operator()(const unique_ptr& __u) const noexcept {} }; template struct _MakeUniq2 { typedef unique_ptr<_Tp> __single_object; }; template struct _MakeUniq2<_Tp[]> { typedef unique_ptr<_Tp[]> __array; }; template struct _MakeUniq2<_Tp[_Bound]> { struct __invalid_type {}; }; /// std::make_unique for single objects template inline typename _MakeUniq2<_Tp>::__single_object make_unique( _Args&&... __args) { return unique_ptr<_Tp>(::new _Tp(std::forward<_Args>(__args)...)); } /// std::make_unique for arrays of unknown bound template inline typename _MakeUniq2<_Tp>::__array make_unique(size_t __num) { return unique_ptr<_Tp>(::new typename remove_extent<_Tp>::type[__num]()); } /// Disable std::make_unique for arrays of known bound template inline typename _MakeUniq2<_Tp>::__invalid_type make_unique(_Args&&...) = delete; INFER_NAMESPACE_STD_END #undef __cast_to_infer_ptr