/* * 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: // 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 {} T* data; // 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)...)); } INFER_NAMESPACE_STD_END