Finish work on deducing this, for now
This commit is contained in:
@ -1,48 +1,48 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "asl/base/utility.hpp"
|
#include "asl/base/utility.hpp"
|
||||||
#include "asl/base/functional.hpp"
|
#include "asl/base/functional.hpp"
|
||||||
|
|
||||||
namespace asl
|
namespace asl
|
||||||
{
|
{
|
||||||
|
|
||||||
template<invocable Callback>
|
template<invocable Callback>
|
||||||
class DeferCallback
|
class DeferCallback
|
||||||
{
|
{
|
||||||
Callback m_callback;
|
Callback m_callback;
|
||||||
bool m_moved = false;
|
bool m_moved = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template<typename T>
|
template<typename T>
|
||||||
explicit DeferCallback(T&& callback) : m_callback(ASL_FWD(callback))
|
explicit DeferCallback(T&& callback) : m_callback(ASL_FWD(callback))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
ASL_DELETE_COPY(DeferCallback);
|
ASL_DELETE_COPY(DeferCallback);
|
||||||
|
|
||||||
DeferCallback(DeferCallback&& other) :
|
DeferCallback(DeferCallback&& other) :
|
||||||
m_callback(ASL_MOVE(other.m_callback)), m_moved(exchange(other.m_moved, true))
|
m_callback(ASL_MOVE(other.m_callback)), m_moved(exchange(other.m_moved, true))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
DeferCallback& operator=(DeferCallback&&) = delete;
|
DeferCallback& operator=(DeferCallback&&) = delete;
|
||||||
|
|
||||||
~DeferCallback()
|
~DeferCallback()
|
||||||
{
|
{
|
||||||
if (!m_moved) { invoke(m_callback); }
|
if (!m_moved) { invoke(m_callback); }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DeferFactory
|
struct DeferFactory
|
||||||
{
|
{
|
||||||
template<invocable Callback>
|
template<invocable Callback>
|
||||||
DeferCallback<Callback> operator<<(Callback&& callback) const
|
DeferCallback<Callback> operator<<(Callback&& callback) const
|
||||||
{
|
{
|
||||||
return DeferCallback<Callback>(ASL_FWD(callback));
|
return DeferCallback<Callback>(ASL_FWD(callback));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace asl
|
} // namespace asl
|
||||||
|
|
||||||
#define ASL_DEFER auto ASL_CONCAT(_defer_, __COUNTER__) = ::asl::DeferFactory{} <<
|
#define ASL_DEFER auto ASL_CONCAT(_defer_, __COUNTER__) = ::asl::DeferFactory{} <<
|
||||||
|
|
||||||
|
@ -1,32 +1,32 @@
|
|||||||
#include "asl/base/defer.hpp"
|
#include "asl/base/defer.hpp"
|
||||||
#include "asl/testing/testing.hpp"
|
#include "asl/testing/testing.hpp"
|
||||||
|
|
||||||
ASL_TEST(defer)
|
ASL_TEST(defer)
|
||||||
{
|
{
|
||||||
uint32_t a = 0;
|
uint32_t a = 0;
|
||||||
|
|
||||||
{
|
{
|
||||||
ASL_DEFER [&a]() { a |= 1; };
|
ASL_DEFER [&a]() { a |= 1; };
|
||||||
ASL_TEST_EXPECT(a == 0);
|
ASL_TEST_EXPECT(a == 0);
|
||||||
|
|
||||||
{
|
{
|
||||||
ASL_DEFER [&a]() { a |= 2; };
|
ASL_DEFER [&a]() { a |= 2; };
|
||||||
ASL_DEFER [&a]() { a |= 4; };
|
ASL_DEFER [&a]() { a |= 4; };
|
||||||
ASL_TEST_EXPECT(a == 0);
|
ASL_TEST_EXPECT(a == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASL_TEST_EXPECT(a == 6);
|
ASL_TEST_EXPECT(a == 6);
|
||||||
|
|
||||||
{
|
{
|
||||||
ASL_DEFER [&a]() { a |= 8; };
|
ASL_DEFER [&a]() { a |= 8; };
|
||||||
ASL_TEST_EXPECT(a == 6);
|
ASL_TEST_EXPECT(a == 6);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASL_TEST_EXPECT(a == 14);
|
ASL_TEST_EXPECT(a == 14);
|
||||||
|
|
||||||
ASL_DEFER [&a]() { a |= 16; };
|
ASL_DEFER [&a]() { a |= 16; };
|
||||||
ASL_TEST_EXPECT(a == 14);
|
ASL_TEST_EXPECT(a == 14);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASL_TEST_EXPECT(a == 31);
|
ASL_TEST_EXPECT(a == 31);
|
||||||
}
|
}
|
||||||
|
@ -8,8 +8,7 @@ template<typename T> static constexpr int identify(T&&) { return 4; }
|
|||||||
|
|
||||||
struct IdentifySelf
|
struct IdentifySelf
|
||||||
{
|
{
|
||||||
template<typename Self>
|
constexpr int get(this auto&& self) { return identify(ASL_FWD(self)); }
|
||||||
constexpr int get(this Self&& self) { return identify(ASL_FWD(self)); }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static int get_const_lref(const IdentifySelf& i) { return ASL_FWD(i).get(); }
|
static int get_const_lref(const IdentifySelf& i) { return ASL_FWD(i).get(); }
|
||||||
|
@ -381,39 +381,31 @@ public:
|
|||||||
return *init;
|
return *init;
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Todo(C++23) Use deducing this
|
auto data(this auto&& self)
|
||||||
const T* data() const
|
|
||||||
{
|
{
|
||||||
|
using return_type = un_ref_t<copy_cref_t<decltype(self), T>>*;
|
||||||
if constexpr (kInlineCapacity == 0)
|
if constexpr (kInlineCapacity == 0)
|
||||||
{
|
{
|
||||||
return m_data;
|
return return_type{ self.m_data };
|
||||||
}
|
}
|
||||||
else
|
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()};
|
||||||
return m_data;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return is_on_heap() ? m_data : reinterpret_cast<T*>(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Todo(C++23) Use deducing this
|
constexpr auto end(this auto&& self)
|
||||||
constexpr contiguous_iterator<const T> begin() const { return contiguous_iterator{data()}; }
|
{
|
||||||
constexpr contiguous_iterator<const T> end() const { return contiguous_iterator{data() + size()}; }
|
using type = un_ref_t<copy_cref_t<decltype(self), T>>;
|
||||||
|
return contiguous_iterator<type>{self.data() + self.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)
|
constexpr operator span<const T>() const // NOLINT(*-explicit-conversions)
|
||||||
{
|
{
|
||||||
return as_span();
|
return as_span();
|
||||||
@ -424,27 +416,16 @@ public:
|
|||||||
return as_span();
|
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()};
|
ASL_ASSERT(i >= 0 && i <= self.size());
|
||||||
}
|
return ASL_FWD_LIKE(decltype(self), ASL_FWD(self).data()[i]);
|
||||||
|
|
||||||
// @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];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename H>
|
template<typename H>
|
||||||
|
@ -147,31 +147,18 @@ public:
|
|||||||
// NOLINTEND(*-pointer-arithmetic)
|
// NOLINTEND(*-pointer-arithmetic)
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Todo(C++23) Deducing this
|
|
||||||
template<typename U>
|
template<typename U>
|
||||||
requires key_hasher<KeyHasher, U> && key_comparator<KeyComparator, K, U>
|
auto get(this auto&& self, const U& value)
|
||||||
const V* get(const U& value) const
|
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)
|
if (index >= 0)
|
||||||
{
|
{
|
||||||
// NOLINTNEXTLINE(*-pointer-arithmetic)
|
// 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;
|
return return_type{ 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;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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)
|
void detach(T* node)
|
||||||
@ -169,25 +171,16 @@ public:
|
|||||||
using iterator = generic_iterator<T>;
|
using iterator = generic_iterator<T>;
|
||||||
using const_iterator = generic_iterator<const T>;
|
using const_iterator = generic_iterator<const T>;
|
||||||
|
|
||||||
// @Todo(C++23) Deduplicate with deducing-this maybe
|
auto begin(this auto&& self)
|
||||||
const_iterator begin() const
|
|
||||||
{
|
{
|
||||||
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
|
|
||||||
{
|
|
||||||
return const_iterator{ head(), true };
|
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator begin()
|
auto end(this auto&& self)
|
||||||
{
|
{
|
||||||
return iterator{ head(), is_empty() };
|
using iterator_type = select_t<is_const<un_ref_t<decltype(self)>>, const_iterator, iterator>;
|
||||||
}
|
return iterator_type{ self.head(), true };
|
||||||
|
|
||||||
iterator end()
|
|
||||||
{
|
|
||||||
return iterator{ head(), true };
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ struct IntNode : public asl::intrusive_list_node<IntNode>
|
|||||||
|
|
||||||
ASL_TEST(empty_list)
|
ASL_TEST(empty_list)
|
||||||
{
|
{
|
||||||
asl::IntrusiveList<IntNode> list;
|
const asl::IntrusiveList<IntNode> list;
|
||||||
ASL_TEST_EXPECT(list.is_empty());
|
ASL_TEST_EXPECT(list.is_empty());
|
||||||
ASL_TEST_EXPECT(list.head() == nullptr);
|
ASL_TEST_EXPECT(list.head() == nullptr);
|
||||||
ASL_TEST_EXPECT(list.tail() == nullptr);
|
ASL_TEST_EXPECT(list.tail() == nullptr);
|
||||||
|
@ -14,12 +14,12 @@ ASL_TEST(custom_writer)
|
|||||||
{
|
{
|
||||||
asl::StringWriter string_writer{};
|
asl::StringWriter string_writer{};
|
||||||
asl::log::DefaultLogger<asl::StringWriter<>&> logger(string_writer);
|
asl::log::DefaultLogger<asl::StringWriter<>&> logger(string_writer);
|
||||||
|
|
||||||
asl::log::register_logger(&logger);
|
asl::log::register_logger(&logger);
|
||||||
ASL_DEFER [&logger]() {
|
ASL_DEFER [&logger]() {
|
||||||
asl::log::unregister_logger(&logger);
|
asl::log::unregister_logger(&logger);
|
||||||
};
|
};
|
||||||
|
|
||||||
ASL_LOG_INFO("Hello");
|
ASL_LOG_INFO("Hello");
|
||||||
auto sv = string_writer.as_string_view();
|
auto sv = string_writer.as_string_view();
|
||||||
|
|
||||||
|
@ -37,34 +37,21 @@ public:
|
|||||||
m_buffer.clear();
|
m_buffer.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Todo(C++23) Deducing this
|
auto push(this auto&& self, string_view sv) -> decltype(self)
|
||||||
|
requires (!is_const<un_ref_t<decltype(self)>>)
|
||||||
StringBuilder& push(string_view sv) &
|
|
||||||
{
|
{
|
||||||
isize_t old_size = m_buffer.size();
|
isize_t old_size = self.m_buffer.size();
|
||||||
m_buffer.resize_zero(old_size + sv.size());
|
self.m_buffer.resize_zero(old_size + sv.size());
|
||||||
asl::memcpy(m_buffer.data() + old_size, sv.data(), sv.size());
|
// NOLINTNEXTLINE(*-pointer-arithmetic)
|
||||||
return *this;
|
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();
|
self.m_buffer.push(c);
|
||||||
m_buffer.resize_zero(old_size + sv.size());
|
return ASL_FWD(self);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
string<Allocator> finish() &&
|
string<Allocator> finish() &&
|
||||||
@ -73,14 +60,14 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<allocator StringAllocator = Allocator>
|
template<allocator StringAllocator = Allocator>
|
||||||
string<StringAllocator> as_string()
|
string<StringAllocator> as_string() const
|
||||||
requires default_constructible<StringAllocator>
|
requires default_constructible<StringAllocator>
|
||||||
{
|
{
|
||||||
return string<StringAllocator>{as_string_view()};
|
return string<StringAllocator>{as_string_view()};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<allocator StringAllocator = Allocator>
|
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)};
|
return string<StringAllocator>{as_string_view(), ASL_MOVE(allocator)};
|
||||||
}
|
}
|
||||||
@ -121,14 +108,14 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<allocator StringAllocator = Allocator>
|
template<allocator StringAllocator = Allocator>
|
||||||
string<StringAllocator> as_string()
|
string<StringAllocator> as_string() const
|
||||||
requires default_constructible<StringAllocator>
|
requires default_constructible<StringAllocator>
|
||||||
{
|
{
|
||||||
return m_builder.as_string();
|
return m_builder.as_string();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<allocator StringAllocator = Allocator>
|
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));
|
return m_builder.as_string(ASL_MOVE(allocator));
|
||||||
}
|
}
|
||||||
@ -136,8 +123,8 @@ public:
|
|||||||
|
|
||||||
StringWriter() -> StringWriter<>;
|
StringWriter() -> StringWriter<>;
|
||||||
|
|
||||||
template<allocator Allocator = DefaultAllocator, formattable... Args>
|
template<allocator Allocator = DefaultAllocator>
|
||||||
string<Allocator> format_to_string(string_view fmt, const Args&... args)
|
string<Allocator> format_to_string(string_view fmt, const formattable auto&... args)
|
||||||
requires default_constructible<Allocator>
|
requires default_constructible<Allocator>
|
||||||
{
|
{
|
||||||
StringWriter writer{};
|
StringWriter writer{};
|
||||||
@ -145,8 +132,8 @@ string<Allocator> format_to_string(string_view fmt, const Args&... args)
|
|||||||
return ASL_MOVE(writer).finish();
|
return ASL_MOVE(writer).finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<allocator Allocator = DefaultAllocator, formattable... Args>
|
template<allocator Allocator = DefaultAllocator>
|
||||||
string<Allocator> format_to_string(Allocator allocator, string_view fmt, const Args&... args)
|
string<Allocator> format_to_string(Allocator allocator, string_view fmt, const formattable auto&... args)
|
||||||
{
|
{
|
||||||
StringWriter writer{ASL_MOVE(allocator)};
|
StringWriter writer{ASL_MOVE(allocator)};
|
||||||
format(&writer, fmt, args...);
|
format(&writer, fmt, args...);
|
||||||
|
@ -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[])
|
int main([[maybe_unused]] int argc, [[maybe_unused]] char* argv[])
|
||||||
{
|
{
|
||||||
asl::set_assert_failure_handler(report_assert_failure, nullptr);
|
asl::set_assert_failure_handler(report_assert_failure, nullptr);
|
||||||
|
|
||||||
int fail = 0;
|
int fail = 0;
|
||||||
int pass = 0;
|
int pass = 0;
|
||||||
|
|
||||||
|
@ -17,9 +17,8 @@ public:
|
|||||||
constexpr maybe_uninit() requires trivially_default_constructible<T> = default;
|
constexpr maybe_uninit() requires trivially_default_constructible<T> = default;
|
||||||
constexpr maybe_uninit() requires (!trivially_default_constructible<T>) {} // NOLINT
|
constexpr maybe_uninit() requires (!trivially_default_constructible<T>) {} // NOLINT
|
||||||
|
|
||||||
template<typename... Args>
|
explicit constexpr maybe_uninit(in_place_t, auto&&... args)
|
||||||
explicit constexpr maybe_uninit(in_place_t, Args&&... args)
|
requires constructible_from<T, decltype(args)...>
|
||||||
requires constructible_from<T, Args&&...>
|
|
||||||
: m_value{ASL_FWD(args)...}
|
: m_value{ASL_FWD(args)...}
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@ -39,17 +38,15 @@ public:
|
|||||||
constexpr ~maybe_uninit() requires (!trivially_destructible<T>) {} // NOLINT
|
constexpr ~maybe_uninit() requires (!trivially_destructible<T>) {} // NOLINT
|
||||||
|
|
||||||
// @Safety Value must not have been initialized yet
|
// @Safety Value must not have been initialized yet
|
||||||
template<typename... Args>
|
constexpr void construct_unsafe(auto&&... args)
|
||||||
constexpr void construct_unsafe(Args&&... args)
|
requires constructible_from<T, decltype(args)...>
|
||||||
requires constructible_from<T, Args&&...>
|
|
||||||
{
|
{
|
||||||
construct_at<T>(&m_value, ASL_FWD(args)...);
|
construct_at<T>(&m_value, ASL_FWD(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Safety Value must have been initialized
|
// @Safety Value must have been initialized
|
||||||
template<typename U>
|
constexpr void assign_unsafe(auto&& value)
|
||||||
constexpr void assign_unsafe(U&& value)
|
requires assignable_from<T&, decltype(value)>
|
||||||
requires assignable_from<T&, U&&>
|
|
||||||
{
|
{
|
||||||
m_value = ASL_FWD(value);
|
m_value = ASL_FWD(value);
|
||||||
}
|
}
|
||||||
@ -64,10 +61,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// @Safety Value must have been initialized
|
// @Safety Value must have been initialized
|
||||||
template<typename Self>
|
constexpr auto&& as_init_unsafe(this auto&& self)
|
||||||
constexpr auto&& as_init_unsafe(this Self&& 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 auto&& self)
|
||||||
constexpr auto&& value(this Self&& self)
|
|
||||||
{
|
{
|
||||||
ASL_ASSERT_RELEASE(self.has_value());
|
ASL_ASSERT_RELEASE(self.has_value());
|
||||||
return ASL_FWD(self).m_payload.as_init_unsafe();
|
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));
|
return has_value() ? ASL_MOVE(value()) : static_cast<T>(ASL_FWD(other_value));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename... Args>
|
constexpr T& emplace(auto&&... args) &
|
||||||
constexpr T& emplace(Args&&... args) &
|
requires constructible_from<T, decltype(args)...>
|
||||||
requires constructible_from<T, Args&&...>
|
|
||||||
{
|
{
|
||||||
if (has_value()) { reset(); }
|
if (has_value()) { reset(); }
|
||||||
construct(ASL_FWD(args)...);
|
construct(ASL_FWD(args)...);
|
||||||
return value();
|
return value();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename F, typename Self>
|
template<typename F>
|
||||||
constexpr auto and_then(this Self&& self, F&& 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>);
|
static_assert(is_option<Result>);
|
||||||
|
|
||||||
if (self.has_value())
|
if (self.has_value())
|
||||||
@ -408,10 +406,10 @@ public:
|
|||||||
return Result{ asl::nullopt };
|
return Result{ asl::nullopt };
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename F, typename Self>
|
template<typename F>
|
||||||
constexpr auto transform(this Self&& self, F&& 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())
|
if (self.has_value())
|
||||||
{
|
{
|
||||||
return option<un_cvref_t<Result>>{
|
return option<un_cvref_t<Result>>{
|
||||||
|
@ -129,8 +129,7 @@ public:
|
|||||||
|
|
||||||
constexpr status&& throw_status() && { return ASL_MOVE(m_status); }
|
constexpr status&& throw_status() && { return ASL_MOVE(m_status); }
|
||||||
|
|
||||||
template<typename Self>
|
constexpr auto&& value(this auto&& self)
|
||||||
constexpr auto&& value(this Self&& self)
|
|
||||||
{
|
{
|
||||||
ASL_ASSERT_RELEASE(self.ok());
|
ASL_ASSERT_RELEASE(self.ok());
|
||||||
return ASL_FWD(self).m_value.as_init_unsafe();
|
return ASL_FWD(self).m_value.as_init_unsafe();
|
||||||
|
Reference in New Issue
Block a user