diff options
author | Steven Le Rouzic <steven.lerouzic@gmail.com> | 2025-02-27 23:58:57 +0100 |
---|---|---|
committer | Steven Le Rouzic <steven.lerouzic@gmail.com> | 2025-02-28 00:30:34 +0100 |
commit | eb285643ed5dab8125e9c6bc94abd7ef562096a5 (patch) | |
tree | 99bb67ae08b15d4de39a8a98b0f9c051dce97546 /asl | |
parent | 38ab48b1882f36ed7eb7e50c4fb46ce5d376fbc3 (diff) |
Finish work on deducing this, for now
Diffstat (limited to 'asl')
-rw-r--r-- | asl/base/defer.hpp | 96 | ||||
-rw-r--r-- | asl/base/defer_tests.cpp | 64 | ||||
-rw-r--r-- | asl/base/utility_tests.cpp | 3 | ||||
-rw-r--r-- | asl/containers/buffer.hpp | 55 | ||||
-rw-r--r-- | asl/containers/hash_map.hpp | 25 | ||||
-rw-r--r-- | asl/containers/intrusive_list.hpp | 31 | ||||
-rw-r--r-- | asl/containers/intrusive_list_tests.cpp | 2 | ||||
-rw-r--r-- | asl/logging/logging_tests.cpp | 4 | ||||
-rw-r--r-- | asl/strings/string_builder.hpp | 51 | ||||
-rw-r--r-- | asl/testing/testing.cpp | 2 | ||||
-rw-r--r-- | asl/types/maybe_uninit.hpp | 20 | ||||
-rw-r--r-- | asl/types/option.hpp | 20 | ||||
-rw-r--r-- | asl/types/status_or.hpp | 3 |
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(); |