|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include <cstddef>
|
|
|
|
|
|
|
|
template <typename T, size_t bits_to_store>
|
|
|
|
struct marked_ptr {
|
|
|
|
static constexpr size_t mask = (1 << bits_to_store) - 1;
|
|
|
|
|
|
|
|
// static_assert(alignof(T) >= (1 << bits_to_store));
|
|
|
|
|
|
|
|
marked_ptr(T* ptr = nullptr) : ptr(ptr) {}
|
|
|
|
|
|
|
|
marked_ptr(T* ptr, size_t mark) : ptr((T*)((size_t)ptr | (mark & mask))) {}
|
|
|
|
|
|
|
|
T* get_ptr() const { return (T*)((size_t)ptr & ~1); }
|
|
|
|
|
|
|
|
size_t get_mark() const { return (size_t)ptr & mask; }
|
|
|
|
|
|
|
|
void set_ptr(T* ptr) { this->ptr = (T*)((size_t)ptr | get_mark()); }
|
|
|
|
|
|
|
|
void set_mark(size_t mark) { ptr = (T*)(((size_t)ptr & ~mask) | (mark & mask)); }
|
|
|
|
|
|
|
|
operator T*() const { return get_ptr(); }
|
|
|
|
|
|
|
|
operator size_t() const { return get_mark(); }
|
|
|
|
|
|
|
|
protected:
|
|
|
|
T* ptr{nullptr};
|
|
|
|
};
|
|
|
|
|
|
|
|
// template <typename T>
|
|
|
|
// struct marked_ptr<T, 1> {
|
|
|
|
// // static_assert(alignof(T) >= 1);
|
|
|
|
|
|
|
|
// marked_ptr(T* ptr = nullptr) : ptr(ptr) {}
|
|
|
|
|
|
|
|
// marked_ptr(T* ptr, bool mark) : ptr((T*)((size_t)ptr | mark)) {}
|
|
|
|
|
|
|
|
// T* get_ptr() const { return (T*)((size_t)ptr & ~1); }
|
|
|
|
|
|
|
|
// bool is_marked() const { return (size_t)ptr & 1; }
|
|
|
|
|
|
|
|
// void set_ptr(T* ptr) { this->ptr = (T*)((size_t)ptr | is_marked()); }
|
|
|
|
|
|
|
|
// void set_mark(bool mark) { ptr = (T*)((size_t)ptr | mark); }
|
|
|
|
|
|
|
|
// operator T*() const { return get_ptr(); }
|
|
|
|
|
|
|
|
// operator bool() const { return is_marked(); }
|
|
|
|
|
|
|
|
// T* operator->() const { return get_ptr(); }
|
|
|
|
|
|
|
|
// protected:
|
|
|
|
// T* ptr{nullptr};
|
|
|
|
// };
|
|
|
|
|
|
|
|
template <typename F, typename T, size_t bits_to_store>
|
|
|
|
inline static marked_ptr<F, bits_to_store> static_pointer_cast(const marked_ptr<T, bits_to_store>& p)
|
|
|
|
{
|
|
|
|
return marked_ptr<F, bits_to_store>(static_cast<F*>(p.get_ptr()), p.get_mark());
|
|
|
|
}
|