Finish work on deducing this, for now
This commit is contained in:
@ -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(); }
|
||||
|
@ -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>
|
||||
|
@ -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 };
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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 };
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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...);
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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>>{
|
||||
|
@ -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();
|
||||
|
Reference in New Issue
Block a user