summaryrefslogtreecommitdiff
path: root/asl
diff options
context:
space:
mode:
authorSteven Le Rouzic <steven.lerouzic@gmail.com>2025-02-27 23:58:57 +0100
committerSteven Le Rouzic <steven.lerouzic@gmail.com>2025-02-28 00:30:34 +0100
commiteb285643ed5dab8125e9c6bc94abd7ef562096a5 (patch)
tree99bb67ae08b15d4de39a8a98b0f9c051dce97546 /asl
parent38ab48b1882f36ed7eb7e50c4fb46ce5d376fbc3 (diff)
Finish work on deducing this, for now
Diffstat (limited to 'asl')
-rw-r--r--asl/base/defer.hpp96
-rw-r--r--asl/base/defer_tests.cpp64
-rw-r--r--asl/base/utility_tests.cpp3
-rw-r--r--asl/containers/buffer.hpp55
-rw-r--r--asl/containers/hash_map.hpp25
-rw-r--r--asl/containers/intrusive_list.hpp31
-rw-r--r--asl/containers/intrusive_list_tests.cpp2
-rw-r--r--asl/logging/logging_tests.cpp4
-rw-r--r--asl/strings/string_builder.hpp51
-rw-r--r--asl/testing/testing.cpp2
-rw-r--r--asl/types/maybe_uninit.hpp20
-rw-r--r--asl/types/option.hpp20
-rw-r--r--asl/types/status_or.hpp3
13 files changed, 158 insertions, 218 deletions
diff --git a/asl/base/defer.hpp b/asl/base/defer.hpp
index e881d8a..122312a 100644
--- a/asl/base/defer.hpp
+++ b/asl/base/defer.hpp
@@ -1,48 +1,48 @@
-#pragma once
-
-#include "asl/base/utility.hpp"
-#include "asl/base/functional.hpp"
-
-namespace asl
-{
-
-template<invocable Callback>
-class DeferCallback
-{
- Callback m_callback;
- bool m_moved = false;
-
-public:
- template<typename T>
- explicit DeferCallback(T&& callback) : m_callback(ASL_FWD(callback))
- {
- }
-
- ASL_DELETE_COPY(DeferCallback);
-
- DeferCallback(DeferCallback&& other) :
- m_callback(ASL_MOVE(other.m_callback)), m_moved(exchange(other.m_moved, true))
- {
- }
-
- DeferCallback& operator=(DeferCallback&&) = delete;
-
- ~DeferCallback()
- {
- if (!m_moved) { invoke(m_callback); }
- }
-};
-
-struct DeferFactory
-{
- template<invocable Callback>
- DeferCallback<Callback> operator<<(Callback&& callback) const
- {
- return DeferCallback<Callback>(ASL_FWD(callback));
- }
-};
-
-} // namespace asl
-
-#define ASL_DEFER auto ASL_CONCAT(_defer_, __COUNTER__) = ::asl::DeferFactory{} <<
-
+#pragma once
+
+#include "asl/base/utility.hpp"
+#include "asl/base/functional.hpp"
+
+namespace asl
+{
+
+template<invocable Callback>
+class DeferCallback
+{
+ Callback m_callback;
+ bool m_moved = false;
+
+public:
+ template<typename T>
+ explicit DeferCallback(T&& callback) : m_callback(ASL_FWD(callback))
+ {
+ }
+
+ ASL_DELETE_COPY(DeferCallback);
+
+ DeferCallback(DeferCallback&& other) :
+ m_callback(ASL_MOVE(other.m_callback)), m_moved(exchange(other.m_moved, true))
+ {
+ }
+
+ DeferCallback& operator=(DeferCallback&&) = delete;
+
+ ~DeferCallback()
+ {
+ if (!m_moved) { invoke(m_callback); }
+ }
+};
+
+struct DeferFactory
+{
+ template<invocable Callback>
+ DeferCallback<Callback> operator<<(Callback&& callback) const
+ {
+ return DeferCallback<Callback>(ASL_FWD(callback));
+ }
+};
+
+} // namespace asl
+
+#define ASL_DEFER auto ASL_CONCAT(_defer_, __COUNTER__) = ::asl::DeferFactory{} <<
+
diff --git a/asl/base/defer_tests.cpp b/asl/base/defer_tests.cpp
index b5139d5..488350f 100644
--- a/asl/base/defer_tests.cpp
+++ b/asl/base/defer_tests.cpp
@@ -1,32 +1,32 @@
-#include "asl/base/defer.hpp"
-#include "asl/testing/testing.hpp"
-
-ASL_TEST(defer)
-{
- uint32_t a = 0;
-
- {
- ASL_DEFER [&a]() { a |= 1; };
- ASL_TEST_EXPECT(a == 0);
-
- {
- ASL_DEFER [&a]() { a |= 2; };
- ASL_DEFER [&a]() { a |= 4; };
- ASL_TEST_EXPECT(a == 0);
- }
-
- ASL_TEST_EXPECT(a == 6);
-
- {
- ASL_DEFER [&a]() { a |= 8; };
- ASL_TEST_EXPECT(a == 6);
- }
-
- ASL_TEST_EXPECT(a == 14);
-
- ASL_DEFER [&a]() { a |= 16; };
- ASL_TEST_EXPECT(a == 14);
- }
-
- ASL_TEST_EXPECT(a == 31);
-}
+#include "asl/base/defer.hpp"
+#include "asl/testing/testing.hpp"
+
+ASL_TEST(defer)
+{
+ uint32_t a = 0;
+
+ {
+ ASL_DEFER [&a]() { a |= 1; };
+ ASL_TEST_EXPECT(a == 0);
+
+ {
+ ASL_DEFER [&a]() { a |= 2; };
+ ASL_DEFER [&a]() { a |= 4; };
+ ASL_TEST_EXPECT(a == 0);
+ }
+
+ ASL_TEST_EXPECT(a == 6);
+
+ {
+ ASL_DEFER [&a]() { a |= 8; };
+ ASL_TEST_EXPECT(a == 6);
+ }
+
+ ASL_TEST_EXPECT(a == 14);
+
+ ASL_DEFER [&a]() { a |= 16; };
+ ASL_TEST_EXPECT(a == 14);
+ }
+
+ ASL_TEST_EXPECT(a == 31);
+}
diff --git a/asl/base/utility_tests.cpp b/asl/base/utility_tests.cpp
index d959369..8fd6479 100644
--- a/asl/base/utility_tests.cpp
+++ b/asl/base/utility_tests.cpp
@@ -8,8 +8,7 @@ template<typename T> static constexpr int identify(T&&) { return 4; }
struct IdentifySelf
{
- template<typename Self>
- constexpr int get(this Self&& self) { return identify(ASL_FWD(self)); }
+ constexpr int get(this auto&& self) { return identify(ASL_FWD(self)); }
};
static int get_const_lref(const IdentifySelf& i) { return ASL_FWD(i).get(); }
diff --git a/asl/containers/buffer.hpp b/asl/containers/buffer.hpp
index 76562d3..3954d35 100644
--- a/asl/containers/buffer.hpp
+++ b/asl/containers/buffer.hpp
@@ -381,39 +381,31 @@ public:
return *init;
}
- // @Todo(C++23) Use deducing this
- const T* data() const
+ auto data(this auto&& self)
{
+ using return_type = un_ref_t<copy_cref_t<decltype(self), T>>*;
if constexpr (kInlineCapacity == 0)
{
- return m_data;
+ return return_type{ self.m_data };
}
else
{
- return is_on_heap() ? m_data : reinterpret_cast<const T*>(this);
+ return self.is_on_heap() ? return_type{ self.m_data } : reinterpret_cast<return_type>(&self);
}
}
- T* data()
+ constexpr auto begin(this auto&& self)
{
- if constexpr (kInlineCapacity == 0)
- {
- return m_data;
- }
- else
- {
- return is_on_heap() ? m_data : reinterpret_cast<T*>(this);
- }
+ using type = un_ref_t<copy_cref_t<decltype(self), T>>;
+ return contiguous_iterator<type>{self.data()};
}
- // @Todo(C++23) Use deducing this
- constexpr contiguous_iterator<const T> begin() const { return contiguous_iterator{data()}; }
- constexpr contiguous_iterator<const T> end() const { return contiguous_iterator{data() + size()}; }
-
- constexpr contiguous_iterator<T> begin() { return contiguous_iterator{data()}; }
- constexpr contiguous_iterator<T> end() { return contiguous_iterator{data() + size()}; }
+ constexpr auto end(this auto&& self)
+ {
+ using type = un_ref_t<copy_cref_t<decltype(self), T>>;
+ return contiguous_iterator<type>{self.data() + self.size()};
+ }
- // @Todo(C++23) Deducing this
constexpr operator span<const T>() const // NOLINT(*-explicit-conversions)
{
return as_span();
@@ -424,27 +416,16 @@ public:
return as_span();
}
- constexpr span<const T> as_span() const
- {
- return span<const T>{data(), size()};
- }
-
- constexpr span<T> as_span()
- {
- return span<T>{data(), size()};
- }
-
- // @Todo(C++23) Use deducing this
- constexpr T& operator[](isize_t i)
+ constexpr auto as_span(this auto&& self)
{
- ASL_ASSERT(i >= 0 && i <= size());
- return data()[i];
+ using type = un_ref_t<copy_cref_t<decltype(self), T>>;
+ return span<type>{self.data(), self.size()};
}
- constexpr const T& operator[](isize_t i) const
+ constexpr auto&& operator[](this auto&& self, isize_t i)
{
- ASL_ASSERT(i >= 0 && i <= size());
- return data()[i];
+ ASL_ASSERT(i >= 0 && i <= self.size());
+ return ASL_FWD_LIKE(decltype(self), ASL_FWD(self).data()[i]);
}
template<typename H>
diff --git a/asl/containers/hash_map.hpp b/asl/containers/hash_map.hpp
index 104bd6a..a59e580 100644
--- a/asl/containers/hash_map.hpp
+++ b/asl/containers/hash_map.hpp
@@ -147,31 +147,18 @@ public:
// NOLINTEND(*-pointer-arithmetic)
}
- // @Todo(C++23) Deducing this
template<typename U>
- requires key_hasher<KeyHasher, U> && key_comparator<KeyComparator, K, U>
- const V* get(const U& value) const
+ auto get(this auto&& self, const U& value)
+ requires key_hasher<KeyHasher, U> && key_comparator<KeyComparator, K, U>
{
- isize_t index = Base::find_slot_lookup(value);
+ using return_type = un_ref_t<copy_cref_t<decltype(self), V>>*;
+ isize_t index = self.find_slot_lookup(value);
if (index >= 0)
{
// NOLINTNEXTLINE(*-pointer-arithmetic)
- return &Base::m_values[index].as_init_unsafe().value;
+ return return_type{ &self.m_values[index].as_init_unsafe().value };
}
- return nullptr;
- }
-
- template<typename U>
- requires key_hasher<KeyHasher, U> && key_comparator<KeyComparator, K, U>
- V* get(const U& value)
- {
- isize_t index = Base::find_slot_lookup(value);
- if (index >= 0)
- {
- // NOLINTNEXTLINE(*-pointer-arithmetic)
- return &Base::m_values[index].as_init_unsafe().value;
- }
- return nullptr;
+ return return_type{ nullptr };
}
};
diff --git a/asl/containers/intrusive_list.hpp b/asl/containers/intrusive_list.hpp
index dcf0508..99509b8 100644
--- a/asl/containers/intrusive_list.hpp
+++ b/asl/containers/intrusive_list.hpp
@@ -76,14 +76,16 @@ public:
}
}
- constexpr T* head() const
+ constexpr auto head(this auto&& self)
{
- return m_head;
+ using return_type = un_ref_t<copy_cref_t<decltype(self), T>>*;
+ return return_type{ self.m_head };
}
- constexpr T* tail() const
+ constexpr auto tail(this auto&& self)
{
- return m_head != nullptr ? m_head->m_prev : nullptr;
+ using return_type = un_ref_t<copy_cref_t<decltype(self), T>>*;
+ return return_type{ self.m_head != nullptr ? self.m_head->m_prev : nullptr };
}
void detach(T* node)
@@ -169,25 +171,16 @@ public:
using iterator = generic_iterator<T>;
using const_iterator = generic_iterator<const T>;
- // @Todo(C++23) Deduplicate with deducing-this maybe
- const_iterator begin() const
+ auto begin(this auto&& self)
{
- return const_iterator{ head(), is_empty() };
- }
-
- const_iterator end() const
- {
- return const_iterator{ head(), true };
+ using iterator_type = select_t<is_const<un_ref_t<decltype(self)>>, const_iterator, iterator>;
+ return iterator_type{ self.head(), self.is_empty() };
}
- iterator begin()
- {
- return iterator{ head(), is_empty() };
- }
-
- iterator end()
+ auto end(this auto&& self)
{
- return iterator{ head(), true };
+ using iterator_type = select_t<is_const<un_ref_t<decltype(self)>>, const_iterator, iterator>;
+ return iterator_type{ self.head(), true };
}
};
diff --git a/asl/containers/intrusive_list_tests.cpp b/asl/containers/intrusive_list_tests.cpp
index ceb54a6..373913c 100644
--- a/asl/containers/intrusive_list_tests.cpp
+++ b/asl/containers/intrusive_list_tests.cpp
@@ -13,7 +13,7 @@ struct IntNode : public asl::intrusive_list_node<IntNode>
ASL_TEST(empty_list)
{
- asl::IntrusiveList<IntNode> list;
+ const asl::IntrusiveList<IntNode> list;
ASL_TEST_EXPECT(list.is_empty());
ASL_TEST_EXPECT(list.head() == nullptr);
ASL_TEST_EXPECT(list.tail() == nullptr);
diff --git a/asl/logging/logging_tests.cpp b/asl/logging/logging_tests.cpp
index d531cda..404f6eb 100644
--- a/asl/logging/logging_tests.cpp
+++ b/asl/logging/logging_tests.cpp
@@ -14,12 +14,12 @@ ASL_TEST(custom_writer)
{
asl::StringWriter string_writer{};
asl::log::DefaultLogger<asl::StringWriter<>&> logger(string_writer);
-
+
asl::log::register_logger(&logger);
ASL_DEFER [&logger]() {
asl::log::unregister_logger(&logger);
};
-
+
ASL_LOG_INFO("Hello");
auto sv = string_writer.as_string_view();
diff --git a/asl/strings/string_builder.hpp b/asl/strings/string_builder.hpp
index d30f1d5..b983bc9 100644
--- a/asl/strings/string_builder.hpp
+++ b/asl/strings/string_builder.hpp
@@ -37,34 +37,21 @@ public:
m_buffer.clear();
}
- // @Todo(C++23) Deducing this
-
- StringBuilder& push(string_view sv) &
+ auto push(this auto&& self, string_view sv) -> decltype(self)
+ requires (!is_const<un_ref_t<decltype(self)>>)
{
- isize_t old_size = m_buffer.size();
- m_buffer.resize_zero(old_size + sv.size());
- asl::memcpy(m_buffer.data() + old_size, sv.data(), sv.size());
- return *this;
+ isize_t old_size = self.m_buffer.size();
+ self.m_buffer.resize_zero(old_size + sv.size());
+ // NOLINTNEXTLINE(*-pointer-arithmetic)
+ asl::memcpy(self.m_buffer.data() + old_size, sv.data(), sv.size());
+ return ASL_FWD(self);
}
- StringBuilder&& push(string_view sv) &&
+ auto push(this auto&& self, char c) -> decltype(self)
+ requires (!is_const<un_ref_t<decltype(self)>>)
{
- isize_t old_size = m_buffer.size();
- m_buffer.resize_zero(old_size + sv.size());
- asl::memcpy(m_buffer.data() + old_size, sv.data(), sv.size());
- return ASL_MOVE(*this);
- }
-
- StringBuilder& push(char c) &
- {
- m_buffer.push(c);
- return *this;
- }
-
- StringBuilder&& push(char c) &&
- {
- m_buffer.push(c);
- return ASL_MOVE(*this);
+ self.m_buffer.push(c);
+ return ASL_FWD(self);
}
string<Allocator> finish() &&
@@ -73,14 +60,14 @@ public:
}
template<allocator StringAllocator = Allocator>
- string<StringAllocator> as_string()
+ string<StringAllocator> as_string() const
requires default_constructible<StringAllocator>
{
return string<StringAllocator>{as_string_view()};
}
template<allocator StringAllocator = Allocator>
- string<StringAllocator> as_string(Allocator allocator)
+ string<StringAllocator> as_string(Allocator allocator) const
{
return string<StringAllocator>{as_string_view(), ASL_MOVE(allocator)};
}
@@ -121,14 +108,14 @@ public:
}
template<allocator StringAllocator = Allocator>
- string<StringAllocator> as_string()
+ string<StringAllocator> as_string() const
requires default_constructible<StringAllocator>
{
return m_builder.as_string();
}
template<allocator StringAllocator = Allocator>
- string<StringAllocator> as_string(Allocator allocator)
+ string<StringAllocator> as_string(Allocator allocator) const
{
return m_builder.as_string(ASL_MOVE(allocator));
}
@@ -136,8 +123,8 @@ public:
StringWriter() -> StringWriter<>;
-template<allocator Allocator = DefaultAllocator, formattable... Args>
-string<Allocator> format_to_string(string_view fmt, const Args&... args)
+template<allocator Allocator = DefaultAllocator>
+string<Allocator> format_to_string(string_view fmt, const formattable auto&... args)
requires default_constructible<Allocator>
{
StringWriter writer{};
@@ -145,8 +132,8 @@ string<Allocator> format_to_string(string_view fmt, const Args&... args)
return ASL_MOVE(writer).finish();
}
-template<allocator Allocator = DefaultAllocator, formattable... Args>
-string<Allocator> format_to_string(Allocator allocator, string_view fmt, const Args&... args)
+template<allocator Allocator = DefaultAllocator>
+string<Allocator> format_to_string(Allocator allocator, string_view fmt, const formattable auto&... args)
{
StringWriter writer{ASL_MOVE(allocator)};
format(&writer, fmt, args...);
diff --git a/asl/testing/testing.cpp b/asl/testing/testing.cpp
index a4eecd7..c788c39 100644
--- a/asl/testing/testing.cpp
+++ b/asl/testing/testing.cpp
@@ -45,7 +45,7 @@ static void report_assert_failure(const char* msg, const asl::source_location& s
int main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[])
{
asl::set_assert_failure_handler(report_assert_failure, nullptr);
-
+
int fail = 0;
int pass = 0;
diff --git a/asl/types/maybe_uninit.hpp b/asl/types/maybe_uninit.hpp
index 36429e4..e8ccbd3 100644
--- a/asl/types/maybe_uninit.hpp
+++ b/asl/types/maybe_uninit.hpp
@@ -17,9 +17,8 @@ public:
constexpr maybe_uninit() requires trivially_default_constructible<T> = default;
constexpr maybe_uninit() requires (!trivially_default_constructible<T>) {} // NOLINT
- template<typename... Args>
- explicit constexpr maybe_uninit(in_place_t, Args&&... args)
- requires constructible_from<T, Args&&...>
+ explicit constexpr maybe_uninit(in_place_t, auto&&... args)
+ requires constructible_from<T, decltype(args)...>
: m_value{ASL_FWD(args)...}
{}
@@ -39,17 +38,15 @@ public:
constexpr ~maybe_uninit() requires (!trivially_destructible<T>) {} // NOLINT
// @Safety Value must not have been initialized yet
- template<typename... Args>
- constexpr void construct_unsafe(Args&&... args)
- requires constructible_from<T, Args&&...>
+ constexpr void construct_unsafe(auto&&... args)
+ requires constructible_from<T, decltype(args)...>
{
construct_at<T>(&m_value, ASL_FWD(args)...);
}
// @Safety Value must have been initialized
- template<typename U>
- constexpr void assign_unsafe(U&& value)
- requires assignable_from<T&, U&&>
+ constexpr void assign_unsafe(auto&& value)
+ requires assignable_from<T&, decltype(value)>
{
m_value = ASL_FWD(value);
}
@@ -64,10 +61,9 @@ public:
}
// @Safety Value must have been initialized
- template<typename Self>
- constexpr auto&& as_init_unsafe(this Self&& self)
+ constexpr auto&& as_init_unsafe(this auto&& self)
{
- return ASL_FWD_LIKE(decltype(self), ASL_FWD(self).m_value);
+ return ASL_FWD(self).m_value;
}
};
diff --git a/asl/types/option.hpp b/asl/types/option.hpp
index b32483b..8b5f313 100644
--- a/asl/types/option.hpp
+++ b/asl/types/option.hpp
@@ -365,8 +365,7 @@ public:
}
}
- template<typename Self>
- constexpr auto&& value(this Self&& self)
+ constexpr auto&& value(this auto&& self)
{
ASL_ASSERT_RELEASE(self.has_value());
return ASL_FWD(self).m_payload.as_init_unsafe();
@@ -386,19 +385,18 @@ public:
return has_value() ? ASL_MOVE(value()) : static_cast<T>(ASL_FWD(other_value));
}
- template<typename... Args>
- constexpr T& emplace(Args&&... args) &
- requires constructible_from<T, Args&&...>
+ constexpr T& emplace(auto&&... args) &
+ requires constructible_from<T, decltype(args)...>
{
if (has_value()) { reset(); }
construct(ASL_FWD(args)...);
return value();
}
- template<typename F, typename Self>
- constexpr auto and_then(this Self&& self, F&& f)
+ template<typename F>
+ constexpr auto and_then(this auto&& self, F&& f)
{
- using Result = invoke_result_t<F, copy_cref_t<Self&&, T>>;
+ using Result = invoke_result_t<F, copy_cref_t<decltype(self), T>>;
static_assert(is_option<Result>);
if (self.has_value())
@@ -408,10 +406,10 @@ public:
return Result{ asl::nullopt };
}
- template<typename F, typename Self>
- constexpr auto transform(this Self&& self, F&& f)
+ template<typename F>
+ constexpr auto transform(this auto&& self, F&& f)
{
- using Result = invoke_result_t<F, copy_cref_t<Self&&, T>>;
+ using Result = invoke_result_t<F, copy_cref_t<decltype(self), T>>;
if (self.has_value())
{
return option<un_cvref_t<Result>>{
diff --git a/asl/types/status_or.hpp b/asl/types/status_or.hpp
index 5771d58..a8a48c1 100644
--- a/asl/types/status_or.hpp
+++ b/asl/types/status_or.hpp
@@ -129,8 +129,7 @@ public:
constexpr status&& throw_status() && { return ASL_MOVE(m_status); }
- template<typename Self>
- constexpr auto&& value(this Self&& self)
+ constexpr auto&& value(this auto&& self)
{
ASL_ASSERT_RELEASE(self.ok());
return ASL_FWD(self).m_value.as_init_unsafe();