What might be wrong with this shared pointer? One good point of it might be, that it should handle array types correctly by default (e.g. light_ptr<int[]>(new int[10]).std::shared_ptr has the advantage of being more portable. For example, emscripten provides an implementation, but light_ptr won't compile, still, it can be ported to emscripten easily. The native implementation may also be more optimized.#pragma once#ifndef LIGHTPTR_HPP# define LIGHTPTR_HPP#include <cassert>#include <atomic>#include <memory>#include <utility>#include <type_traits>namespace detail{  using counter_type = ::std::size_t;  using atomic_type = ::std::atomic<counter_type>;  template <typename T>  using deleter_type = void (*)(T*);  template <typename U>  struct ref_type  {    using type = U&;  };  template <>  struct ref_type<void>  {    using type = void;  };  template <typename T>  inline void dec_ref(atomic_type* const counter_ptr,    T* const ptr, deleter_type<T> const deleter)  {    if (counter_ptr && (counter_type(1) ==      counter_ptr->fetch_sub(counter_type(1), ::std::memory_order_relaxed)))    {      delete counter_ptr;      deleter(ptr);    }    // else do nothing  }  inline void inc_ref(atomic_type* const counter_ptr)  {    assert(counter_ptr);    counter_ptr->fetch_add(counter_type(1), ::std::memory_order_relaxed);  }}template <typename T>struct light_ptr{  template <typename U, typename V>  struct deletion_type  {    using type = V;  };  template <typename U, typename V>  struct deletion_type<U[], V>  {    using type = V[];  };  template <typename U, typename V, ::std::size_t N>  struct deletion_type<U[N], V>  {    using type = V[];  };  template <typename U>  struct remove_array  {    using type = U;  };  template <typename U>  struct remove_array<U[]>  {    using type = U;  };  template <typename U, ::std::size_t N>  struct remove_array<U[N]>  {    using type = U;  };  using element_type = typename remove_array<T>::type;  using deleter_type = ::detail::deleter_type<element_type>;  light_ptr() = default;  template <typename U>  explicit light_ptr(U* const p,    deleter_type const d = default_deleter<U>)  {    reset(p, d);  }  ~light_ptr() { ::detail::dec_ref(counter_ptr_, ptr_, deleter_); }  light_ptr(light_ptr const& other) { *this = other; }  light_ptr(light_ptr&& other) noexcept { *this = ::std::move(other); }  light_ptr& operator=(light_ptr const& rhs)  {    if (*this != rhs)    {      ::detail::dec_ref(counter_ptr_, ptr_, deleter_);      counter_ptr_ = rhs.counter_ptr_;      ptr_ = rhs.ptr_;      deleter_ = rhs.deleter_;      ::detail::inc_ref(counter_ptr_);    }    // else do nothing    return *this;  }  light_ptr& operator=(light_ptr&& rhs) noexcept  {    if (*this != rhs)    {      counter_ptr_ = rhs.counter_ptr_;      ptr_ = rhs.ptr_;      deleter_ = rhs.deleter_;      rhs.counter_ptr_ = nullptr;      rhs.ptr_ = nullptr;    }    // else do nothing    return *this;  }  bool operator<(light_ptr const& rhs) const noexcept  {    return get() < rhs.get();  }  bool operator==(light_ptr const& rhs) const noexcept  {    return counter_ptr_ == rhs.counter_ptr_;  }  bool operator!=(light_ptr const& rhs) const noexcept  {    return !operator==(rhs);  }  bool operator==(::std::nullptr_t const) const noexcept  {    return !ptr_;  }  bool operator!=(::std::nullptr_t const) const noexcept  {    return ptr_;  }  explicit operator bool() const noexcept { return ptr_; }  typename ::detail::ref_type<T>::type  operator*() const noexcept  {    return *static_cast<T*>(static_cast<void*>(ptr_));  }  T* operator->() const noexcept  {    return static_cast<T*>(static_cast<void*>(ptr_));  }  element_type* get() const noexcept { return ptr_; }  void reset() { reset(nullptr); }  void reset(::std::nullptr_t const)  {    ::detail::dec_ref(counter_ptr_, ptr_, deleter_);    counter_ptr_ = nullptr;    ptr_ = nullptr;  }  template <typename U>  void reset(U* const p, deleter_type const d = default_deleter<U>)  {    ::detail::dec_ref(counter_ptr_, ptr_, deleter_);    counter_ptr_ = new ::detail::atomic_type(::detail::counter_type(1));    ptr_ = p;    deleter_ = d;  }  void swap(light_ptr& other) noexcept  {    ::std::swap(counter_ptr_, other.counter_ptr_);    ::std::swap(ptr_, other.ptr_);    ::std::swap(deleter_, other.deleter_);  }  bool unique() const noexcept  {    return ::detail::counter_type(1) == use_count();  }  ::detail::counter_type use_count() const noexcept  {    return counter_ptr_ ?      counter_ptr_->load(::std::memory_order_relaxed) :      ::detail::counter_type{};  }  template <typename U>  static void default_deleter(element_type* const p)  {    ::std::default_delete<typename deletion_type<T, U>::type>()(      static_cast<U*>(p));  }private:  ::detail::atomic_type* counter_ptr_{};  element_type* ptr_{};  deleter_type deleter_;};template<class T, class ...Args>inline light_ptr<T> make_light(Args&& ...args){  return light_ptr<T>(new T(::std::forward<Args>(args)...));}namespace std{  template <typename T>  struct hash<light_ptr<T> >  {    size_t operator()(light_ptr<T> const& l) const noexcept    {      return hash<typename light_ptr<T>::element_type*>(l.get());    }  };}#endif // LIGHTPTR_HPPUsage:#include <iostream>#include <thread>#include <vector>#include lightptr.hppint main(){  {    light_ptr<int> p(new int);    *p = 10;    light_ptr<int> s(p);    p.reset(new int);    std::cout << s.use_count() << :  << *s << std::endl;    std::vector<light_ptr<float> > v(1000000);    for (auto& r: v)    {      r.reset(new float);      *r = 100;    }    auto a(make_light<char[4]>());    (*a)[2] = 10;    a.get()[3] = 10;    ::std::thread a_([&p]{light_ptr<int> a(p); std::cout << p.use_count() << std::endl;});    ::std::thread b_([&p]{light_ptr<int> a(p); std::cout << p.use_count() << std::endl;});    ::std::thread c_([&p]{light_ptr<int> a(p); std::cout << p.use_count() << std::endl;});    ::std::thread d_([&p]{light_ptr<int> a(p); std::cout << p.use_count() << std::endl;});    ::std::thread e_([&p]{light_ptr<int> a(p); std::cout << p.use_count() << std::endl;});    ::std::thread f_([&p]{light_ptr<int> a(p); std::cout << p.use_count() << std::endl;});    ::std::thread g_([&p]{light_ptr<int> a(p); std::cout << p.use_count() << std::endl;});    ::std::thread h_([&p]{light_ptr<int> a(p); std::cout << p.use_count() << std::endl;});    a_.join(); b_.join(); c_.join(); d_.join();    e_.join(); f_.join(); g_.join(); h_.join();  }  struct A  {    ~A() { std::cout << deleted << std::endl; }  };  light_ptr<void> a(new A);  light_ptr<A[]> b(new A[1]);  return 0;}
Yet another shared pointer
c++;c++11;reinventing the wheel;pointers