Finish work on deducing this, for now

This commit is contained in:
2025-02-27 23:58:57 +01:00
parent 38ab48b188
commit eb285643ed
14 changed files with 159 additions and 219 deletions

View File

@ -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(); }

View File

@ -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)
using type = un_ref_t<copy_cref_t<decltype(self), T>>;
return contiguous_iterator<type>{self.data()};
}
constexpr auto end(this auto&& self)
{
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() + self.size()};
}
// @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()}; }
// @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
constexpr auto as_span(this auto&& self)
{
return span<const T>{data(), size()};
using type = un_ref_t<copy_cref_t<decltype(self), T>>;
return span<type>{self.data(), self.size()};
}
constexpr span<T> as_span()
constexpr auto&& operator[](this auto&& self, isize_t i)
{
return span<T>{data(), size()};
}
// @Todo(C++23) Use deducing this
constexpr T& operator[](isize_t i)
{
ASL_ASSERT(i >= 0 && i <= size());
return data()[i];
}
constexpr const T& operator[](isize_t i) const
{
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>

View File

@ -147,31 +147,18 @@ public:
// NOLINTEND(*-pointer-arithmetic)
}
// @Todo(C++23) Deducing this
template<typename U>
auto get(this auto&& self, const U& value)
requires key_hasher<KeyHasher, U> && key_comparator<KeyComparator, K, U>
const V* get(const U& value) const
{
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 };
}
};

View File

@ -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() };
using iterator_type = select_t<is_const<un_ref_t<decltype(self)>>, const_iterator, iterator>;
return iterator_type{ self.head(), self.is_empty() };
}
const_iterator end() const
auto end(this auto&& self)
{
return const_iterator{ head(), true };
}
iterator begin()
{
return iterator{ head(), is_empty() };
}
iterator end()
{
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 };
}
};

View File

@ -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);

View File

@ -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...);

View File

@ -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;
}
};

View File

@ -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>>{

View File

@ -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();

View File

@ -1 +1 @@
license