#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