Skip to content

A minimal std::expected<T, E> #12

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
fixup: Add error() observer
  • Loading branch information
deanberris committed Feb 1, 2019
commit 4b7c4d97790ce1b1c9dd3fb6cf3b3d03e9fe3e61
28 changes: 28 additions & 0 deletions netlib/expected.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#ifndef CPP_NETLIB_EXPECTED_H_
#define CPP_NETLIB_EXPECTED_H_

#include <cassert>
#include <type_traits>
#include <utility>

Expand Down Expand Up @@ -206,6 +207,33 @@ class expected {

constexpr explicit operator bool() const noexcept { return has_value_; }

// Observer functions.
constexpr const E& error() const& {
assert(!has_value_ &&
"expected<T, E> must not have a value when taking an error!");
return reinterpret_cast<const unexpected<E>*>(&union_storage_)->value();
}

constexpr E& error() & {
assert(!has_value_ &&
"expected<T, E> must not have a value when taking an error!");
return reinterpret_cast<unexpected<E>*>(&union_storage_)->value();
}

constexpr const E&& error() const&& {
assert(!has_value_ &&
"expected<T, E> must not have a value when taking an error!");
return std::move(*reinterpret_cast<const unexpected<E>*>(&union_storage_))
->value();
}

constexpr E&& error() && {
assert(!has_value_ &&
"expected<T, E> must not have a value when taking an error!");
return std::move(*reinterpret_cast<unexpected<E>*>(&union_storage_))
->value();
};

private:
std::aligned_union_t<8, value_type, unexpected_type> union_storage_;
bool has_value_;
Expand Down
26 changes: 22 additions & 4 deletions netlib/expected_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
namespace cppnetlib {
namespace {

using ::testing::Eq;

using error_code = int;

enum errors : error_code { undefined };
Expand All @@ -27,13 +29,29 @@ expected<bool, error_code> f(bool b) {
return unexpected(errors::undefined);
}

// For testing support for larger types.
struct test_data {
int64_t first;
int64_t second;
};

expected<test_data, error_code> g(bool b, int64_t first, int64_t second) {
if (b) return unexpected{errors::undefined};
return test_data{first, second};
}

TEST(ExpectedTest, Construction) { expected<bool, error_code> e; }

TEST(ExpectedTest, Unexpected) {
auto e = f(true);
auto g = f(false);
ASSERT_FALSE(g);
ASSERT_TRUE(e);
auto e1 = f(true);
ASSERT_TRUE(e1);

auto e2 = f(false);
ASSERT_FALSE(e2);

auto e3 = g(true, 1, 2);
ASSERT_FALSE(e2);
EXPECT_THAT(e3.error(), Eq(errors::undefined));
}

} // namespace
Expand Down