Finish work on hashing probably
This commit is contained in:
@ -5,6 +5,7 @@
|
||||
#include "asl/annotations.hpp"
|
||||
#include "asl/memory.hpp"
|
||||
#include "asl/utility.hpp"
|
||||
#include "asl/hash.hpp"
|
||||
|
||||
namespace asl
|
||||
{
|
||||
@ -82,6 +83,13 @@ public:
|
||||
{
|
||||
return m_ptr == nullptr;
|
||||
}
|
||||
|
||||
template<typename H>
|
||||
requires hashable<T>
|
||||
friend H AslHashValue(H h, const box& b)
|
||||
{
|
||||
return H::combine(ASL_MOVE(h), *b);
|
||||
}
|
||||
};
|
||||
|
||||
template<is_object T, allocator Allocator = DefaultAllocator, typename... Args>
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "asl/memory.hpp"
|
||||
#include "asl/assert.hpp"
|
||||
#include "asl/span.hpp"
|
||||
#include "asl/hash.hpp"
|
||||
|
||||
namespace asl
|
||||
{
|
||||
@ -391,6 +392,7 @@ public:
|
||||
}
|
||||
|
||||
template<typename H>
|
||||
requires hashable<T>
|
||||
friend H AslHashValue(H h, const buffer& b)
|
||||
{
|
||||
return H::combine_contiguous(ASL_MOVE(h), b.as_span());
|
||||
|
@ -120,6 +120,12 @@ constexpr H AslHashValue(H h, bool value)
|
||||
template<typename H, typename T>
|
||||
constexpr void AslHashValue(H h, T*); // Don't hash pointers
|
||||
|
||||
template<typename H, hashable T>
|
||||
constexpr H AslHashValue(H h, const span<T>& s)
|
||||
{
|
||||
return H::combine_contiguous(ASL_MOVE(h), span<const T>{s.data(), s.size()});
|
||||
}
|
||||
|
||||
template<hashable T>
|
||||
constexpr uint64_t hash_value(const T& value)
|
||||
{
|
||||
|
@ -197,7 +197,7 @@ template<is_enum T> struct is_uniquely_represented<T> : true_type {};
|
||||
template<> struct is_uniquely_represented<uint128_t> : true_type {};
|
||||
template<> struct is_uniquely_represented<byte> : true_type {};
|
||||
|
||||
template<typename T> concept uniquely_represented = is_uniquely_represented<T>::value;
|
||||
template<typename T> concept uniquely_represented = is_uniquely_represented<un_cv_t<T>>::value;
|
||||
|
||||
template<typename T, typename U>
|
||||
concept equality_comparable_with = requires (const un_cvref_t<T>& a, const un_cvref_t<U>& b)
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "asl/maybe_uninit.hpp"
|
||||
#include "asl/functional.hpp"
|
||||
#include "asl/annotations.hpp"
|
||||
#include "asl/hash.hpp"
|
||||
|
||||
namespace asl
|
||||
{
|
||||
@ -485,8 +486,23 @@ public:
|
||||
{
|
||||
return has_value() ? ASL_MOVE(*this) : invoke(ASL_FWD(f));
|
||||
}
|
||||
|
||||
template<typename H>
|
||||
requires (!uniquely_represented<option>) && hashable<T>
|
||||
friend H AslHashValue(H h, const option& opt)
|
||||
{
|
||||
if (!opt.has_value())
|
||||
{
|
||||
return H::combine(ASL_MOVE(h), 0);
|
||||
}
|
||||
return H::combine(ASL_MOVE(h), 1, opt.value());
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
requires has_niche<T> && uniquely_represented<T>
|
||||
struct is_uniquely_represented<option<T>> : true_type {};
|
||||
|
||||
template<typename T>
|
||||
option(T) -> option<T>;
|
||||
|
||||
|
@ -171,12 +171,6 @@ public:
|
||||
ASL_ASSERT(sub_size >= 0 && sub_size <= size());
|
||||
return span<T>{ data() + size() - sub_size, sub_size };
|
||||
}
|
||||
|
||||
template<typename H>
|
||||
friend H AslHashValue(H h, const span& s)
|
||||
{
|
||||
return H::combine_contiguous(ASL_MOVE(h), span<const T>{s.data(), s.size()});
|
||||
}
|
||||
};
|
||||
|
||||
template<is_object T, isize_t kSize>
|
||||
|
@ -104,9 +104,6 @@ public:
|
||||
return m_payload == nullptr;
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(*-explicit-conversions)
|
||||
constexpr operator bool() const { return ok(); }
|
||||
|
||||
constexpr status_code code() const
|
||||
{
|
||||
return is_inline() ? code_inline() : code_internal();
|
||||
@ -122,6 +119,16 @@ public:
|
||||
}
|
||||
|
||||
friend void AslFormat(Formatter& f, const status&);
|
||||
|
||||
template<typename H>
|
||||
friend H AslHashValue(H h, const status& s)
|
||||
{
|
||||
if (s.is_inline())
|
||||
{
|
||||
return H::combine(ASL_MOVE(h), s.code());
|
||||
}
|
||||
return H::combine(ASL_MOVE(h), s.code(), s.message());
|
||||
}
|
||||
};
|
||||
|
||||
static constexpr status ok() { return status{status_code::ok}; }
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include "asl/status.hpp"
|
||||
#include "asl/maybe_uninit.hpp"
|
||||
#include "asl/hash.hpp"
|
||||
|
||||
namespace asl
|
||||
{
|
||||
@ -122,9 +123,6 @@ public:
|
||||
|
||||
constexpr bool ok() const { return m_status.ok(); }
|
||||
|
||||
// NOLINTNEXTLINE(*-explicit-conversions)
|
||||
constexpr operator bool() const { return m_status; }
|
||||
|
||||
constexpr status_code code() const { return m_status.code(); }
|
||||
|
||||
constexpr string_view message() const { return m_status.message(); }
|
||||
@ -161,6 +159,17 @@ public:
|
||||
{
|
||||
return ok() ? ASL_MOVE(value()) : static_cast<T>(ASL_FWD(other_value));
|
||||
}
|
||||
|
||||
template<typename H>
|
||||
requires hashable<T>
|
||||
friend H AslHashValue(H h, const status_or& s)
|
||||
{
|
||||
if (s.ok())
|
||||
{
|
||||
return H::combine(ASL_MOVE(h), s.m_status, s.value());
|
||||
}
|
||||
return H::combine(ASL_MOVE(h), s.m_status);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
|
@ -3,6 +3,10 @@
|
||||
#include "asl/string_view.hpp"
|
||||
#include "asl/string.hpp"
|
||||
#include "asl/buffer.hpp"
|
||||
#include "asl/box.hpp"
|
||||
#include "asl/option.hpp"
|
||||
#include "asl/status.hpp"
|
||||
#include "asl/status_or.hpp"
|
||||
|
||||
static_assert(!asl::hashable<int*>);
|
||||
static_assert(!asl::hashable<int[]>);
|
||||
@ -57,6 +61,7 @@ ASL_TEST(strings)
|
||||
}
|
||||
|
||||
static_assert(asl::hashable<asl::span<const int>>);
|
||||
static_assert(!asl::hashable<asl::span<const int*>>);
|
||||
static_assert(asl::hashable<asl::span<asl::string_view>>);
|
||||
|
||||
ASL_TEST(span)
|
||||
@ -81,6 +86,7 @@ ASL_TEST(span)
|
||||
}
|
||||
|
||||
static_assert(asl::hashable<asl::buffer<int>>);
|
||||
static_assert(!asl::hashable<asl::buffer<int*>>);
|
||||
|
||||
ASL_TEST(buffer)
|
||||
{
|
||||
@ -137,6 +143,118 @@ enum class Enum2 {};
|
||||
static_assert(asl::hashable<Enum1>);
|
||||
static_assert(asl::hashable<Enum2>);
|
||||
|
||||
// @Todo option (optimize uniquely_represented + has_niche)
|
||||
// @Todo status, status_or
|
||||
// @Todo box
|
||||
static_assert(!asl::hashable<asl::box<int*>>);
|
||||
static_assert(asl::hashable<asl::box<asl::string_view>>);
|
||||
|
||||
ASL_TEST(box)
|
||||
{
|
||||
auto b1 = asl::make_box<asl::string_view>("Hello, world!");
|
||||
auto b2 = asl::make_box<asl::string_view>("Hello, world!");
|
||||
auto b3 = asl::make_box<asl::string_view>("Hello, world! 2");
|
||||
|
||||
ASL_TEST_EXPECT(asl::hash_value(b1) == asl::hash_value(b2));
|
||||
ASL_TEST_EXPECT(asl::hash_value(b1) != asl::hash_value(b3));
|
||||
ASL_TEST_EXPECT(asl::hash_value(b1) == asl::hash_value("Hello, world!"_sv));
|
||||
}
|
||||
|
||||
struct NonZero
|
||||
{
|
||||
int value;
|
||||
|
||||
constexpr explicit NonZero(int x) : value(x)
|
||||
{
|
||||
ASL_ASSERT(x != 0);
|
||||
}
|
||||
|
||||
constexpr explicit NonZero(asl::niche_t) : value(0) {}
|
||||
|
||||
constexpr bool operator==(asl::niche_t) const { return value == 0; }
|
||||
};
|
||||
|
||||
namespace asl { template<> struct is_uniquely_represented<NonZero> : true_type {}; }
|
||||
static_assert(asl::has_niche<NonZero>);
|
||||
static_assert(asl::uniquely_represented<NonZero>);
|
||||
|
||||
static_assert(asl::hashable<asl::option<int>>);
|
||||
static_assert(!asl::hashable<asl::option<int*>>);
|
||||
static_assert(asl::hashable<asl::option<asl::string_view>>);
|
||||
static_assert(asl::hashable<asl::option<NonZero>>);
|
||||
static_assert(asl::uniquely_represented<asl::option<NonZero>>);
|
||||
|
||||
ASL_TEST(option)
|
||||
{
|
||||
asl::option<int> int1 = 0;
|
||||
asl::option<int> int2 = 0;
|
||||
asl::option<int> int3 = 1;
|
||||
asl::option<int> int4 = asl::nullopt;
|
||||
|
||||
ASL_TEST_EXPECT(asl::hash_value(int1) == asl::hash_value(int2));
|
||||
ASL_TEST_EXPECT(asl::hash_value(int1) != asl::hash_value(int3));
|
||||
ASL_TEST_EXPECT(asl::hash_value(int1) != asl::hash_value(int4));
|
||||
|
||||
asl::option<NonZero> noz1{8};
|
||||
asl::option<NonZero> noz2{8};
|
||||
asl::option<NonZero> noz3{9};
|
||||
asl::option<NonZero> noz4 = asl::nullopt;
|
||||
|
||||
ASL_TEST_EXPECT(asl::hash_value(noz1) == asl::hash_value(noz2));
|
||||
ASL_TEST_EXPECT(asl::hash_value(noz1) != asl::hash_value(noz3));
|
||||
ASL_TEST_EXPECT(asl::hash_value(noz1) != asl::hash_value(noz4));
|
||||
}
|
||||
|
||||
static_assert(asl::hashable<asl::status>);
|
||||
|
||||
ASL_TEST(status)
|
||||
{
|
||||
asl::status s1 = asl::ok();
|
||||
asl::status s2 = asl::ok();
|
||||
asl::status s3 = asl::internal_error();
|
||||
asl::status s4 = asl::internal_error();
|
||||
asl::status s5 = asl::runtime_error();
|
||||
asl::status s6 = asl::internal_error("Oh, no!");
|
||||
asl::status s7 = asl::internal_error("Oh, no!");
|
||||
asl::status s8 = asl::internal_error("Oh, no");
|
||||
asl::status s9 = asl::runtime_error("Oh, no!");
|
||||
|
||||
ASL_TEST_EXPECT(asl::hash_value(s1) == asl::hash_value(s2));
|
||||
ASL_TEST_EXPECT(asl::hash_value(s3) == asl::hash_value(s4));
|
||||
ASL_TEST_EXPECT(asl::hash_value(s6) == asl::hash_value(s7));
|
||||
|
||||
ASL_TEST_EXPECT(asl::hash_value(s1) != asl::hash_value(s3));
|
||||
ASL_TEST_EXPECT(asl::hash_value(s1) != asl::hash_value(s5));
|
||||
ASL_TEST_EXPECT(asl::hash_value(s1) != asl::hash_value(s6));
|
||||
ASL_TEST_EXPECT(asl::hash_value(s1) != asl::hash_value(s9));
|
||||
|
||||
ASL_TEST_EXPECT(asl::hash_value(s3) != asl::hash_value(s5));
|
||||
ASL_TEST_EXPECT(asl::hash_value(s3) != asl::hash_value(s6));
|
||||
ASL_TEST_EXPECT(asl::hash_value(s3) != asl::hash_value(s8));
|
||||
ASL_TEST_EXPECT(asl::hash_value(s3) != asl::hash_value(s9));
|
||||
|
||||
ASL_TEST_EXPECT(asl::hash_value(s6) != asl::hash_value(s8));
|
||||
ASL_TEST_EXPECT(asl::hash_value(s6) != asl::hash_value(s9));
|
||||
}
|
||||
|
||||
static_assert(asl::hashable<asl::status_or<int>>);
|
||||
static_assert(asl::hashable<asl::status_or<asl::string_view>>);
|
||||
static_assert(!asl::hashable<asl::status_or<int*>>);
|
||||
|
||||
ASL_TEST(status_or)
|
||||
{
|
||||
asl::status_or<int> s1 = 42;
|
||||
asl::status_or<int> s2 = 42;
|
||||
asl::status_or<int> s3 = 43;
|
||||
asl::status_or<int> s4 = asl::runtime_error();
|
||||
asl::status_or<int> s5 = asl::runtime_error();
|
||||
asl::status_or<int> s6 = asl::runtime_error("Hello");
|
||||
asl::status_or<int> s7 = asl::runtime_error("Hello");
|
||||
|
||||
ASL_TEST_EXPECT(asl::hash_value(s1) == asl::hash_value(s2));
|
||||
ASL_TEST_EXPECT(asl::hash_value(s4) == asl::hash_value(s5));
|
||||
ASL_TEST_EXPECT(asl::hash_value(s6) == asl::hash_value(s7));
|
||||
|
||||
ASL_TEST_EXPECT(asl::hash_value(s1) != asl::hash_value(s3));
|
||||
ASL_TEST_EXPECT(asl::hash_value(s1) != asl::hash_value(s4));
|
||||
ASL_TEST_EXPECT(asl::hash_value(s1) != asl::hash_value(s6));
|
||||
|
||||
ASL_TEST_EXPECT(asl::hash_value(s4) != asl::hash_value(s6));
|
||||
}
|
||||
|
@ -18,7 +18,6 @@ ASL_TEST(ok)
|
||||
{
|
||||
asl::status_or<int> s = 6;
|
||||
ASL_TEST_EXPECT(s.ok());
|
||||
ASL_TEST_EXPECT(s);
|
||||
ASL_TEST_EXPECT(s.code() == asl::status_code::ok);
|
||||
}
|
||||
|
||||
@ -26,19 +25,16 @@ ASL_TEST(from_status)
|
||||
{
|
||||
asl::status_or<char> s = asl::internal_error();
|
||||
ASL_TEST_EXPECT(!s.ok());
|
||||
ASL_TEST_EXPECT(!s);
|
||||
ASL_TEST_EXPECT(s.code() == asl::status_code::internal);
|
||||
ASL_TEST_EXPECT(s.message() == ""_sv);
|
||||
|
||||
asl::status_or<int> s2 = asl::internal_error("oh no");
|
||||
ASL_TEST_EXPECT(!s2.ok());
|
||||
ASL_TEST_EXPECT(!s2);
|
||||
ASL_TEST_EXPECT(s2.code() == asl::status_code::internal);
|
||||
ASL_TEST_EXPECT(s2.message() == "oh no"_sv);
|
||||
|
||||
asl::status_or<int> s3 = asl::internal_error("{} {}", 1, 2);
|
||||
ASL_TEST_EXPECT(!s3.ok());
|
||||
ASL_TEST_EXPECT(!s3);
|
||||
ASL_TEST_EXPECT(s3.code() == asl::status_code::internal);
|
||||
ASL_TEST_EXPECT(s3.message() == "1 2"_sv);
|
||||
}
|
||||
|
@ -6,7 +6,6 @@
|
||||
ASL_TEST(simple_ok)
|
||||
{
|
||||
asl::status s = asl::ok();
|
||||
ASL_TEST_ASSERT(s);
|
||||
ASL_TEST_ASSERT(s.ok());
|
||||
ASL_TEST_ASSERT(s.code() == asl::status_code::ok);
|
||||
}
|
||||
@ -14,7 +13,6 @@ ASL_TEST(simple_ok)
|
||||
ASL_TEST(simple_code)
|
||||
{
|
||||
asl::status s = asl::runtime_error();
|
||||
ASL_TEST_ASSERT(!s);
|
||||
ASL_TEST_ASSERT(!s.ok());
|
||||
ASL_TEST_ASSERT(s.code() == asl::status_code::runtime);
|
||||
ASL_TEST_ASSERT(s.message() == ""_sv);
|
||||
@ -23,7 +21,6 @@ ASL_TEST(simple_code)
|
||||
ASL_TEST(with_message)
|
||||
{
|
||||
asl::status s = asl::internal_error("We done goofed");
|
||||
ASL_TEST_ASSERT(!s);
|
||||
ASL_TEST_ASSERT(!s.ok());
|
||||
ASL_TEST_ASSERT(s.code() == asl::status_code::internal);
|
||||
ASL_TEST_ASSERT(s.message() == "We done goofed"_sv);
|
||||
@ -47,25 +44,21 @@ ASL_TEST(copy_message)
|
||||
|
||||
{
|
||||
asl::status s = asl::internal_error("Oh no!");
|
||||
ASL_TEST_ASSERT(!s);
|
||||
ASL_TEST_ASSERT(!s.ok());
|
||||
ASL_TEST_ASSERT(s.code() == asl::status_code::internal);
|
||||
ASL_TEST_ASSERT(s.message() == "Oh no!"_sv);
|
||||
|
||||
const asl::status s3{s}; // NOLINT
|
||||
ASL_TEST_ASSERT(!s3);
|
||||
ASL_TEST_ASSERT(!s3.ok());
|
||||
ASL_TEST_ASSERT(s3.code() == asl::status_code::internal);
|
||||
ASL_TEST_ASSERT(s3.message() == "Oh no!"_sv);
|
||||
|
||||
s2 = s;
|
||||
ASL_TEST_ASSERT(!s2);
|
||||
ASL_TEST_ASSERT(!s2.ok());
|
||||
ASL_TEST_ASSERT(s2.code() == asl::status_code::internal);
|
||||
ASL_TEST_ASSERT(s2.message() == "Oh no!"_sv);
|
||||
}
|
||||
|
||||
ASL_TEST_ASSERT(!s2);
|
||||
ASL_TEST_ASSERT(!s2.ok());
|
||||
ASL_TEST_ASSERT(s2.code() == asl::status_code::internal);
|
||||
ASL_TEST_ASSERT(s2.message() == "Oh no!"_sv);
|
||||
|
Reference in New Issue
Block a user