Some improvements to the nullable interface

This commit is contained in:
Jeremy Rifkin 2025-02-01 19:10:19 -06:00
parent 248ad447b1
commit 85be7c32a4
No known key found for this signature in database
GPG Key ID: 19AA8270105E8EB4
2 changed files with 26 additions and 15 deletions

View File

@ -95,37 +95,42 @@ namespace cpptrace {
// use.
template<typename T, typename std::enable_if<std::is_integral<T>::value, int>::type = 0>
struct nullable {
T raw_value;
nullable& operator=(T value) {
T raw_value = null_value();
constexpr nullable() noexcept = default;
constexpr nullable(T value) noexcept : raw_value(value) {}
constexpr nullable& operator=(T value) noexcept {
raw_value = value;
return *this;
}
bool has_value() const noexcept {
return raw_value != (std::numeric_limits<T>::max)();
constexpr bool has_value() const noexcept {
return raw_value != null_value();
}
T& value() noexcept {
constexpr T& value() noexcept {
return raw_value;
}
const T& value() const noexcept {
constexpr const T& value() const noexcept {
return raw_value;
}
T value_or(T alternative) const noexcept {
constexpr T value_or(T alternative) const noexcept {
return has_value() ? raw_value : alternative;
}
void swap(nullable& other) noexcept {
constexpr void swap(nullable& other) noexcept {
std::swap(raw_value, other.raw_value);
}
void reset() noexcept {
constexpr void reset() noexcept {
raw_value = (std::numeric_limits<T>::max)();
}
bool operator==(const nullable& other) const noexcept {
constexpr bool operator==(const nullable& other) const noexcept {
return raw_value == other.raw_value;
}
bool operator!=(const nullable& other) const noexcept {
constexpr bool operator!=(const nullable& other) const noexcept {
return raw_value != other.raw_value;
}
constexpr static T null_value() noexcept {
return (std::numeric_limits<T>::max)();
}
constexpr static nullable null() noexcept {
return { (std::numeric_limits<T>::max)() };
return { null_value() };
}
};

View File

@ -13,20 +13,26 @@ TEST(NullableTest, Basic) {
nullable<std::uint32_t> a{12};
EXPECT_EQ(a.value(), 12);
EXPECT_EQ(a.raw_value, 12);
// TODO: =
nullable<std::uint32_t> b = 20;
EXPECT_EQ(b.value(), 20);
}
TEST(NullableTest, Null) {
auto a = nullable<std::uint32_t>::null();
EXPECT_FALSE(a.has_value());
EXPECT_EQ(a.raw_value, (std::numeric_limits<std::uint32_t>::max)());
// TODO: default construct
nullable<std::uint32_t> b;
EXPECT_FALSE(b.has_value());
EXPECT_EQ(b.raw_value, nullable<std::uint32_t>::null_value());
}
TEST(NullableTest, Assignment) {
nullable<std::uint32_t> a;
a = 12;
EXPECT_EQ(a.value(), 12);
nullable<std::uint32_t> b = 20;
a = b;
EXPECT_EQ(a.value(), 20);
}
TEST(NullableTest, Reset) {
@ -49,7 +55,7 @@ TEST(NullableTest, Comparison) {
TEST(NullableTest, Swap) {
auto a = nullable<std::uint32_t>::null();
nullable<std::uint32_t> b{12};
nullable<std::uint32_t> b = 12;
EXPECT_FALSE(a.has_value());
EXPECT_EQ(b.value(), 12);
a.swap(b);