diff --git a/include/cpptrace/basic.hpp b/include/cpptrace/basic.hpp index b5fb4ea..b32b0c7 100644 --- a/include/cpptrace/basic.hpp +++ b/include/cpptrace/basic.hpp @@ -95,37 +95,42 @@ namespace cpptrace { // use. template::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::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::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::max)(); + } constexpr static nullable null() noexcept { - return { (std::numeric_limits::max)() }; + return { null_value() }; } }; diff --git a/test/unit/lib/nullable.cpp b/test/unit/lib/nullable.cpp index 1d1dd54..66663b6 100644 --- a/test/unit/lib/nullable.cpp +++ b/test/unit/lib/nullable.cpp @@ -13,20 +13,26 @@ TEST(NullableTest, Basic) { nullable a{12}; EXPECT_EQ(a.value(), 12); EXPECT_EQ(a.raw_value, 12); - // TODO: = + nullable b = 20; + EXPECT_EQ(b.value(), 20); } TEST(NullableTest, Null) { auto a = nullable::null(); EXPECT_FALSE(a.has_value()); EXPECT_EQ(a.raw_value, (std::numeric_limits::max)()); - // TODO: default construct + nullable b; + EXPECT_FALSE(b.has_value()); + EXPECT_EQ(b.raw_value, nullable::null_value()); } TEST(NullableTest, Assignment) { nullable a; a = 12; EXPECT_EQ(a.value(), 12); + nullable 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::null(); - nullable b{12}; + nullable b = 12; EXPECT_FALSE(a.has_value()); EXPECT_EQ(b.value(), 12); a.swap(b);