summaryrefslogtreecommitdiff
path: root/src/unique_ptr.hh
diff options
context:
space:
mode:
authorMaxime Coste <mawww@kakoune.org>2025-07-08 11:43:17 +1000
committerMaxime Coste <mawww@kakoune.org>2025-07-08 12:07:33 +1000
commitce1d512a0c1922ab5f43f28e7bae573508c98601 (patch)
tree7af8effd6b00c304cda1c87f657a0014fcdae2ae /src/unique_ptr.hh
parentfea08fc18d268ace4f843ec2b57cc33e36562098 (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.hh69
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