/* * 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 // ASSERT that __cplusplus >= 201103L #include INFER_NAMESPACE_STD_BEGIN // use inheritance to avoid compilation errors when using // methods / non-member functions that are not modeled // WARNING: sizeof(shared_ptr) = 24, not 16 - this may // lead to compilation errors template class shared_ptr : public std__shared_ptr { public: #if INFER_USE_LIBCPP using std__shared_ptr::__ptr_; #define __data __ptr_ #else using __shared_ptr::_M_ptr; #define __data _M_ptr #endif // Conversion constructors to allow implicit conversions. // it's here purely to avoid compilation errors template ::value>::type> shared_ptr(const std__shared_ptr& r) {} template shared_ptr(const std__shared_ptr& r, T* p) noexcept {} // constructors: constexpr shared_ptr() noexcept { __data = nullptr; } shared_ptr(nullptr_t) : shared_ptr() {} // Extra template argument is used to create constructors/assignment overloads // for Y types where it's possible to convert Y* to T*. // typename = typename enable_if::value>::type // thanks to that, clang will not create some functions that would cause // compilation errors. More info: // http://en.cppreference.com/w/cpp/language/sfinae template ::value>::type> explicit shared_ptr(Y* p) { __data = p; } template ::value>::type> shared_ptr(Y* p, D d) : shared_ptr(p) {} template ::value>::type> shared_ptr(Y* p, D d, A a) : shared_ptr(p) {} template shared_ptr(nullptr_t p, D d) : shared_ptr(p) {} template shared_ptr(nullptr_t p, D d, A a) : shared_ptr(p) {} template shared_ptr(const shared_ptr& r, T* p) noexcept { __data = nullptr; /* TODO */ } shared_ptr(const shared_ptr& r) noexcept : shared_ptr(r.__data) { /* TODO - increase refcount*/ } template ::value>::type> shared_ptr(const shared_ptr& r) noexcept : shared_ptr(r.__data) { /* TODO - increase refcount*/ } shared_ptr(shared_ptr&& r) noexcept : shared_ptr(r.__data) { r.__data = nullptr; } template ::value>::type> shared_ptr(shared_ptr&& r) noexcept : shared_ptr(r.__data) { r.__data = nullptr; } template ::value>::type> explicit shared_ptr(const weak_ptr& r) {} /* Because of implementation differences between libc++ and stdlibc++, don't * define this constructor (it will be defined elsewhere in case of * stdlibc++). Because it may be defined elsewhere, don't check whether Y* * converts to T* - otherwise there might be compilation error (out-of-line * definition). * No definition here might cause compilation problems if project is * using auto_ptrs with libc++ */ template shared_ptr(auto_ptr&& r); // {} template ::value>::type> shared_ptr(unique_ptr&& r) : shared_ptr(r.release()) {} // destructor: ~shared_ptr() { reset((T*)nullptr); } // assignment: shared_ptr& operator=(const shared_ptr& r) noexcept { // shared_ptr(r).swap(*this); __data = r.__data; return *this; } template ::value>::type> shared_ptr& operator=(const shared_ptr& r) noexcept { // shared_ptr(r).swap(*this); __data = r.__data; return *this; } shared_ptr& operator=(shared_ptr&& r) noexcept { // shared_ptr(std::move(r)).swap(*this); __data = r.__data; return *this; } template ::value>::type> shared_ptr& operator=(shared_ptr&& r) { // shared_ptr(std::move(r)).swap(*this); __data = r.__data; return *this; } template ::value>::type> shared_ptr& operator=(auto_ptr&& r) { /* ?? */ } template ::value>::type> shared_ptr& operator=(unique_ptr&& r) { // shared_ptr(std::move(r)).swap(*this); return *this; } // modifiers: void swap(shared_ptr& r) noexcept { T* tmp = r.__data; r.__data = __data; __data = tmp; } void reset() noexcept { reset((T*)nullptr); } template ::value>::type> void reset(Y* p) { /* if (unique()) { delete __data; } */ __data = p; // TODO adjust refcounts } template ::value>::type> void reset(Y* p, D d) { reset(p); } template ::value>::type> void reset(Y* p, D d, A a) { reset(p); } // observers: T* get() const noexcept { return __data; } typename add_lvalue_reference::type operator*() const noexcept { return *__data; } T* operator->() const noexcept { return __data; } long use_count() const noexcept { return 2; /* FIXME */ } bool unique() const noexcept { return use_count() == 1; /* FIXME */ } explicit operator bool() const noexcept { return (bool)__data; } template bool owner_before(shared_ptr const& b) const { return true; /* FIXME - use non-det*/ } template bool owner_before(weak_ptr const& b) const { return true; /* FIXME - use non-det */ } }; template struct hash> : public hash> {}; // shared_ptr casts - call original functions but change return type to // std::shared_ptr template shared_ptr static_pointer_cast(shared_ptr const& r) noexcept { return static_pointer_cast((const std__shared_ptr&)r); } template shared_ptr dynamic_pointer_cast(shared_ptr const& r) noexcept { return dynamic_pointer_cast((const std__shared_ptr&)r); } template shared_ptr const_pointer_cast(shared_ptr const& r) noexcept { return const_pointer_cast((const std__shared_ptr&)r); } template shared_ptr make_shared(Args&&... args) { return shared_ptr(new T(std::forward(args)...)); } #undef __data INFER_NAMESPACE_STD_END