diff options
| author | Maxime Coste <mawww@kakoune.org> | 2025-07-08 11:43:17 +1000 |
|---|---|---|
| committer | Maxime Coste <mawww@kakoune.org> | 2025-07-08 12:07:33 +1000 |
| commit | ce1d512a0c1922ab5f43f28e7bae573508c98601 (patch) | |
| tree | 7af8effd6b00c304cda1c87f657a0014fcdae2ae /src/unique_ptr.hh | |
| parent | fea08fc18d268ace4f843ec2b57cc33e36562098 (diff) | |
Replace std::unique_ptr with a custom implementation
<memory> is a costly header we can avoid by just implementing
UniquePtr ourselves, which is a pretty straightforward in modern
C++, this saves around 10% of the compilation time here.
Diffstat (limited to 'src/unique_ptr.hh')
| -rw-r--r-- | src/unique_ptr.hh | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/src/unique_ptr.hh b/src/unique_ptr.hh new file mode 100644 index 00000000..86f9ac86 --- /dev/null +++ b/src/unique_ptr.hh @@ -0,0 +1,69 @@ +#ifndef unique_ptr_hh_INCLUDED +#define unique_ptr_hh_INCLUDED + +#include <utility> +#include <type_traits> +#include <cstddef> + +namespace Kakoune +{ + +template<typename T> +class UniquePtr +{ + using Type = std::remove_extent_t<T>; + +public: + explicit UniquePtr(Type* ptr = nullptr) : m_ptr{ptr} {} + UniquePtr(nullptr_t) : m_ptr{nullptr} {} + + UniquePtr(const UniquePtr&) = delete; + UniquePtr& operator=(const UniquePtr&) = delete; + + template<typename U> requires std::is_convertible_v<U*, T*> + UniquePtr(UniquePtr<U>&& other) noexcept { m_ptr = other.release(); } + + template<typename U> requires std::is_convertible_v<U*, T*> + UniquePtr& operator=(UniquePtr<U>&& other) noexcept(noexcept(std::declval<Type>().~Type())) + { + destroy(); + m_ptr = other.release(); + return *this; + } + ~UniquePtr() { destroy(); } + + Type* get() const { return m_ptr; } + Type* operator->() const { return m_ptr; }; + Type& operator*() const { return *m_ptr; }; + Type& operator[](size_t i) const requires std::is_array_v<T> { return m_ptr[i]; } + Type* release() { auto ptr = m_ptr; m_ptr = nullptr; return ptr; } + + void reset(Type* ptr = nullptr) { destroy(); m_ptr = ptr; } + + explicit operator bool() const { return m_ptr != nullptr; } + + friend bool operator==(const UniquePtr&, const UniquePtr&) = default; + friend bool operator==(const UniquePtr& lhs, const Type* rhs) { return lhs.get() == rhs; } + +private: + void destroy() + { + if constexpr (std::is_array_v<T>) + delete[] m_ptr; + else + delete m_ptr; + m_ptr = nullptr; + } + + Type* m_ptr; +}; + +template<typename T, typename... Args> +UniquePtr<T> make_unique_ptr(Args&&... args) +{ + return UniquePtr<T>(new T(std::forward<Args>(args)...)); +} + +} + +#endif // unique_ptr_hh_INCLUDED |
