Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
11 changes: 11 additions & 0 deletions include/result/err.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#pragma once

#include <string>

namespace res {

struct Err : public std::string {
Err(const std::string& err_msg) : std::string(err_msg) {}
Err(const char* err_msg) : std::string(err_msg) {}
};
}
12 changes: 0 additions & 12 deletions include/result/internal/err_msg.hpp

This file was deleted.

7 changes: 0 additions & 7 deletions include/result/internal/ok.hpp

This file was deleted.

8 changes: 8 additions & 0 deletions include/result/ok.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#pragma once

namespace res {

struct Ok {
Ok() {}
};
}
27 changes: 12 additions & 15 deletions include/result/result.hpp
Original file line number Diff line number Diff line change
@@ -1,29 +1,26 @@
#pragma once

#include "internal/err_msg.hpp"
#include "internal/ok.hpp"
#include "err.hpp"
#include "ok.hpp"
#include <exception>
#include <memory>
#include <optional>

namespace res {

class Result {
private:
internal::ErrMsgPtr err_msg_ptr;
std::optional<Err> err_opt;
public:
Result() : err_msg_ptr(internal::uninitialized_err_msg_ptr) {}
Result(const internal::Ok& ok) {}
Result(const internal::ErrMsgPtr& err_msg_ptr) : err_msg_ptr(err_msg_ptr) {}
Result() : err_opt(Err("result is uninitialized")) {}
Result(const Ok& ok) {}
Result(const Err& err) : err_opt(err) {}

template<typename E>
Result(const E& err_msg) : err_msg_ptr(std::make_shared<internal::ErrMsg>(err_msg)) {}
bool is_ok() const { return !err_opt.has_value(); }
bool is_err() const { return err_opt.has_value(); }

bool is_ok() const { return !err_msg_ptr; }
bool is_err() const { return (bool)err_msg_ptr; }

internal::ErrMsg unwrap_err() const {
if (!err_msg_ptr) throw std::runtime_error("is ok");
return *err_msg_ptr;
Err unwrap_err() const {
if (!err_opt.has_value()) throw std::runtime_error("is ok");
return err_opt.value();
} // LCOV_EXCL_LINE
};
}
26 changes: 14 additions & 12 deletions test/result_test.cpp
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
#include <result/result.hpp>
#include <catch2/catch_test_macros.hpp>
#include <string>

TEST_CASE("check ok result") {
const res::Result res = res::ok;
const res::Result res = res::Ok();
REQUIRE(res.is_ok());
REQUIRE_FALSE(res.is_err());
}

TEST_CASE("check error result") {
const res::Result res = "unknown error";
const res::Result res = res::Err("unknown error");
REQUIRE(res.is_err());
REQUIRE_FALSE(res.is_ok());
}
Expand All @@ -19,36 +20,37 @@ TEST_CASE("uninitialized result contains error") {
}

TEST_CASE("call `unwrap_err` on error result") {
const res::internal::ErrMsg err_msg = "unknown error";
const res::Result res = err_msg;
const std::string err_msg = "unknown error";
const res::Result res = res::Err(err_msg);
REQUIRE(res.is_err());
REQUIRE(res.unwrap_err() == err_msg);
}

TEST_CASE("call `unwrap_err` on ok result") {
const res::Result res = res::ok;
const res::Result res = res::Ok();
REQUIRE(res.is_ok());
REQUIRE_THROWS(res.unwrap_err());
}

TEST_CASE("check rewriting result") {
res::Result res = res::ok;
res::Result res = res::Ok();
REQUIRE(res.is_ok());
res::internal::ErrMsg err_msg = "unknown error";
res = err_msg;
std::string err_msg = "unknown error";
res = res::Err(err_msg);
REQUIRE(res.is_err());
REQUIRE(res.unwrap_err() == err_msg);
res = err_msg = "other error";
err_msg = "other error";
res = res::Err(err_msg);
REQUIRE(res.is_err());
REQUIRE(res.unwrap_err() == err_msg);
res = res::ok;
res = res::Ok();
REQUIRE(res.is_ok());
}

namespace {
res::Result foo(bool is_ok) {
if (is_ok) return res::ok;
return "unknown error";
if (is_ok) return res::Ok();
return res::Err("unknown error");
}
}

Expand Down