Skip to content

Commit

Permalink
Add emplacement constructors
Browse files Browse the repository at this point in the history
  • Loading branch information
RauliL committed Oct 10, 2024
1 parent a8451c7 commit 1126e2a
Show file tree
Hide file tree
Showing 2 changed files with 147 additions and 80 deletions.
18 changes: 18 additions & 0 deletions include/peelo/result.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,15 @@ namespace peelo
return { new value_type(value), nullptr };
}

/**
* Constructs an successful result from given arguments.
*/
template<class... Args>
static inline result<T, E> ok(Args&&... args)
{
return { new value_type(args...), nullptr };
}

/**
* Constructs an erroneous result with given error.
*/
Expand All @@ -58,6 +67,15 @@ namespace peelo
return { nullptr, new error_type(error) };
}

/**
* Constructs an erroneous result from given arguments.
*/
template<class... Args>
static inline result<T, E> error(Args&&... args)
{
return { nullptr, new error_type(args...) };
}

/**
* Copy constructor.
*/
Expand Down
209 changes: 129 additions & 80 deletions test/test_result.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,177 +3,226 @@

#include <peelo/result.hpp>

struct value
{
int numeric;
std::string text;
};
#define ASSERT_TRUE(x) assert((x))
#define ASSERT_FALSE(x) assert(!(x))
#define ASSERT_EQ(x, y) assert((x) == (y))
#define ASSERT_NE(x, y) assert((x) != (y))

struct error
{
int code;
std::string message;
};

using result = peelo::result<value, error>;
bool
operator==(const error& a, const error& b)
{
return a.code == b.code && a.message == b.message;
}

using result = peelo::result<std::string, error>;

static void
test_ok()
{
const result r = result::ok({ 5, "five" });
const std::string message("hello");
const auto r = result::ok(message);

assert(bool(r) == true);
assert(!r == false);
assert(r->numeric == 5);
assert(r->text == "five");
ASSERT_TRUE(r);
ASSERT_FALSE(!r);
ASSERT_EQ(r.value(), message);
ASSERT_EQ(*r, message);
}

static void
test_ok_emplacement()
{
const auto r = result::ok("hello");

ASSERT_TRUE(r);
ASSERT_FALSE(!r);
ASSERT_EQ(r.value(), "hello");
ASSERT_EQ(*r, "hello");
}

static void
test_error()
{
const result r = result::error({ 404, "Not Found" });
const error e = { 500, "Internal Server Error" };
const auto r = result::error(e);

assert(bool(r) == false);
assert(!r == true);
assert(r.error().code == 404);
assert(r.error().message == "Not Found");
ASSERT_FALSE(r);
ASSERT_TRUE(!r);
ASSERT_EQ(r.error(), e);
}

static void
test_copy_ok()
test_error_emplacement()
{
const result original = result::ok({ 5, "Five" });
const result copy(original);
const auto r = result::error({ 404, "Not Found" });

assert(bool(copy) == bool(original));
assert(copy->numeric == original->numeric);
ASSERT_FALSE(r);
ASSERT_TRUE(!r);
ASSERT_EQ(r.error().code, 404);
ASSERT_EQ(r.error().message, "Not Found");
}

static void
test_copy_error()
test_copy_ok()
{
const result original = result::error({ 404, "Not Found"});
const auto original = result::ok("hello");
const result copy(original);

assert(bool(copy) == bool(original));
assert(copy.error().code == original.error().code);
ASSERT_EQ(bool(original), bool(copy));
ASSERT_EQ(original.value(), copy.value());
}

static void
test_copy_ok_with_different_types()
test_copy_ok_from_different_type()
{
using result1 = peelo::result<int, error>;
using result2 = peelo::result<double, error>;
const result1 original = result1::ok(5);

const auto original = result1::ok(42);
const result2 copy(original);

assert(bool(copy) == bool(original));
assert(*copy == *original);
ASSERT_EQ(bool(original), bool(copy));
ASSERT_EQ(original.value(), copy.value());
}

static void
test_copy_error_with_different_types()
test_copy_error()
{
using result1 = peelo::result<int, error>;
using result2 = peelo::result<double, error>;
const result1 original = result1::error({ 404, "Not Found"});
const result2 copy(original);
const auto original = result::error({ 404, "Not Found" });
const result copy(original);

assert(!copy);
assert(copy.error().code == original.error().code);
ASSERT_EQ(bool(original), bool(copy));
ASSERT_EQ(original.error(), copy.error());
}

static void
test_assign_ok()
test_copy_error_from_different_type()
{
const result ok = result::ok({ 5, "Five" });
result r = result::error({ 400, "Bad Request" });
using result1 = peelo::result<std::string, int>;
using result2 = peelo::result<std::string, double>;

r = ok;
const auto original = result1::error(42);
const result2 copy(original);

assert(bool(r));
assert(r->numeric == ok->numeric);
ASSERT_EQ(bool(original), bool(copy));
ASSERT_EQ(original.error(), copy.error());
}

static void
test_assign_error()
test_assign_ok()
{
const result err = result::error({ 500, "Internal Server Error" });
result r = result::ok({ 1, "One"});
auto r1 = result::ok("hello");
const auto r2 = result::ok("world");

r = err;
r1 = r2;

assert(!r);
assert(r.error().code == err.error().code);
ASSERT_EQ(bool(r1), bool(r2));
ASSERT_EQ(r1.value(), r2.value());
}

static void
test_assign_ok_with_different_types()
test_assign_ok_from_different_type()
{
using result1 = peelo::result<int, error>;
using result2 = peelo::result<double, error>;
const result1 ok = result1::ok(5);
result2 r = result2::error({ 400, "Bad Request" });

r = ok;
auto r1 = result1::ok(42);
const auto r2 = result2::ok(15);

r1 = r2;

assert(bool(r));
assert(r.value() == ok.value());
ASSERT_EQ(bool(r1), bool(r2));
ASSERT_EQ(r1.value(), r2.value());
}

static void
test_assign_error_with_different_types()
test_assign_error()
{
using result1 = peelo::result<int, error>;
using result2 = peelo::result<double, error>;
const result1 err = result1::error({ 500, "Internal Server Error" });
result2 r = result2::ok(1);
auto r1 = result::ok("hello");
const auto r2 = result::error({ 404, "Not Found" });

r = err;
r1 = r2;

assert(!r);
assert(r.error().code == err.error().code);
ASSERT_EQ(bool(r1), bool(r2));
ASSERT_EQ(r1.error(), r2.error());
}

static void
test_assign_error_from_different_type()
{
using result1 = peelo::result<std::string, int>;
using result2 = peelo::result<std::string, double>;

auto r1 = result1::ok("hello");
const auto r2 = result2::error(42);

r1 = r2;

ASSERT_EQ(bool(r1), bool(r2));
ASSERT_EQ(r1.error(), r2.error());
}

static void
test_value_or()
{
using my_result = peelo::result<int, std::string>;
const auto ok = my_result::ok(5);
const auto err = my_result::error("Error message");
const auto r1 = result::ok("hello");
const auto r2 = result::error({ 403, "Forbidden" });

assert(ok.value_or(10) == 5);
assert(err.value_or(10) == 10);
ASSERT_EQ(r1.value_or("goodbye"), "hello");
ASSERT_EQ(r2.value_or("goodbye"), "goodbye");
}

static void
test_equals()
{
using my_result = peelo::result<int, std::string>;
const auto ok1 = my_result::ok(1);
const auto ok2 = my_result::ok(2);
const auto err1 = my_result::error("Unauthorized");
const auto err2 = my_result::error("I'm a teapot");
const auto r1 = result::ok("hello");
const auto r2 = result::error({ 404, "Not found" });

ASSERT_EQ(r1, r1);
ASSERT_EQ(r2, r2);

ASSERT_NE(r1, r2);
ASSERT_NE(r1, result::ok("goodbye"));
ASSERT_NE(r2, result::error({ 418, "I'm a teapot" }));
}

static void
test_equals_from_different_type()
{
using result1 = peelo::result<int, double>;
using result2 = peelo::result<double, int>;

ASSERT_EQ(result1::ok(4), result2::ok(4));
ASSERT_EQ(result1::error(4), result2::error(4));

ASSERT_NE(result1::ok(4), result2::error(4));
ASSERT_NE(result1::ok(1), result2::ok(2));

assert(ok1 == ok1);
assert(ok1 != ok2);
assert(err1 == err1);
assert(err1 != err2);
ASSERT_NE(result1::error(1), result2::ok(1));
ASSERT_NE(result1::ok(1), result2::error(1));
}

int
main()
{
test_ok();
test_ok_emplacement();
test_error();
test_error_emplacement();
test_copy_ok();
test_copy_ok_from_different_type();
test_copy_error();
test_copy_ok_with_different_types();
test_copy_error_with_different_types();
test_copy_error_from_different_type();
test_assign_ok();
test_assign_ok_from_different_type();
test_assign_error();
test_assign_ok_with_different_types();
test_assign_error_with_different_types();
test_assign_error_from_different_type();
test_value_or();
test_equals();
test_equals_from_different_type();
}

0 comments on commit 1126e2a

Please sign in to comment.