[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/github/codeql/codeql-cli/v2.27.1/cpp/ql/test/include/memory.h [Back]  [Original]

#if !defined(CODEQL_MEMORY_H)
#define CODEQL_MEMORY_H

namespace std {
  namespace detail {
    template
    class compressed_pair_element {
      T element;

    public:
      compressed_pair_element() = default;
      compressed_pair_element(const T& t) : element(t) {}
      
      T& get() { return element; }

      const T& get() const { return element; }
    };

    template
    struct compressed_pair : private compressed_pair_element, private compressed_pair_element {
      compressed_pair() = default;
      compressed_pair(T& t) : compressed_pair_element(t), compressed_pair_element() {}
      compressed_pair(const compressed_pair&) = delete;
      compressed_pair(compressed_pair&&) noexcept = default;

      T& first() { return static_cast(*this).get(); }
      U& second() { return static_cast(*this).get(); }

      const T& first() const { return static_cast(*this).get(); }
      const U& second() const { return static_cast(*this).get(); }
    };
  }

  template
  struct default_delete {
    void operator()(T* ptr) const { delete ptr; }
  };

  template
  struct default_delete {
    template
    void operator()(U* ptr) const { delete[] ptr; }
  };

  template
  class unique_ptr {
  private:
    detail::compressed_pair data;
  public:
    constexpr unique_ptr() noexcept {}
    explicit unique_ptr(T* ptr) noexcept : data(ptr) {}
    unique_ptr(const unique_ptr& ptr) = delete;
    unique_ptr(unique_ptr&& ptr) noexcept = default;

    unique_ptr& operator=(unique_ptr&& ptr) noexcept = default;

    T& operator*() const { return *get(); }
    T* operator->() const noexcept { return get(); }

    T* get() const noexcept { return data.first(); }
    T* release() noexcept { 
        Deleter& d = data.second();
        d(data.first());
        data.first() = nullptr;
    }

    ~unique_ptr() {
      Deleter& d = data.second();
      d(data.first());
    }
  };
  
  template unique_ptr make_unique(Args&&... args) {
    return unique_ptr(new T(args...)); // std::forward calls elided for simplicity.
  }

  class ctrl_block {
    unsigned uses;

  public:
    ctrl_block() : uses(1) {}

    void inc() { ++uses; }
    bool dec() { return --uses == 0; }

    virtual void destroy() = 0;
    virtual ~ctrl_block() {}
  };

  template
  struct ctrl_block_impl: public ctrl_block {
    T* ptr;
    Deleter d;

    ctrl_block_impl(T* ptr, Deleter d) : ptr(ptr), d(d) {}
    virtual void destroy() override { d(ptr); }
  };

  template
  class shared_ptr {
  private:
    ctrl_block* ctrl;
    T* ptr;

    void dec() {
      if(ctrl->dec()) {
        ctrl->destroy();
        delete ctrl;
      }
    }

    void inc() {
      ctrl->inc();
    }

  public:
    constexpr shared_ptr() noexcept = default;
    shared_ptr(T* ptr) : ctrl(new ctrl_block_impl(ptr, default_delete())) {}
    shared_ptr(const shared_ptr& s) noexcept : ptr(s.ptr), ctrl(s.ctrl) {
      inc();
    }
    shared_ptr(shared_ptr&& s) noexcept = default;
    shared_ptr(unique_ptr&& s) : shared_ptr(s.release()) {
    }
    T* operator->() const { return ptr; }

    T& operator*() const { return *ptr; }

    T* get() const noexcept { return ptr; }

    ~shared_ptr() { dec(); }
  };

  template shared_ptr make_shared(Args&&... args) {
    return shared_ptr(new T(args...)); // std::forward calls elided for simplicity.
  }
}

#endif

Web Proxy Viewer  |  New URL  |  Original Page