Skip to content

Commit

Permalink
Merge pull request #2 from peelonet/simplification
Browse files Browse the repository at this point in the history
Simplify usage of the class
  • Loading branch information
RauliL authored Feb 9, 2024
2 parents d3b6c52 + 43617b2 commit b817d51
Show file tree
Hide file tree
Showing 6 changed files with 164 additions and 117 deletions.
18 changes: 18 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: Build

on: [push]

jobs:
build:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
steps:
- uses: actions/checkout@v4
- name: Build
uses: ashutoshvarma/action-cmake-build@master
with:
build-dir: ${{ runner.workspace }}/build
build-type: Release
run-test: true
6 changes: 3 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
CMAKE_MINIMUM_REQUIRED(VERSION 3.12)
CMAKE_MINIMUM_REQUIRED(VERSION 3.6)

PROJECT(
PeeloResult
VERSION 0.1.0
VERSION 0.2.0
DESCRIPTION "Header only C++ result type."
HOMEPAGE_URL "https://github.com/peelonet/peelo-result"
LANGUAGES CXX
Expand All @@ -22,7 +22,7 @@ TARGET_INCLUDE_DIRECTORIES(
TARGET_COMPILE_FEATURES(
${PROJECT_NAME}
INTERFACE
cxx_std_17
cxx_std_11
)

INSTALL(
Expand Down
13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# peelo-result

[![travis][travis-image]][travis-url]
![Build](https://github.com/peelonet/peelo-result/workflows/Build/badge.svg)

Header only C++11 implementation of [Rust's Result type].

Expand All @@ -17,9 +17,10 @@ Header only C++11 implementation of [Rust's Result type].
and `error`. First one creates an "OK" result, which holds some kind of value,
while the second one creates erroneous result which holds some kind of error.

Type of the error can be checked with the `type` method of `result` class. If
the result is of type `result::type::ok`, then it's value can be accessed with
the `value` method, otherwise it's error can be accessed with `error` method.
Whether an result contains an value or not can be checked with `has_value`
method of `result` class. If this method returns `true`, then it's value can be
accessed with the `value` method, otherwise it's error can be accessed with
the `error` method.

**Note**: The underlying containers are implemented with [std::unique_ptr], so
accessing `value` of erroneous result leads to undefined behavior and vice
Expand Down Expand Up @@ -47,12 +48,12 @@ int main()

if (ok_result)
{
std::cout << "OK result: " << *ok_result.value() << std::endl;
std::cout << "OK result: " << ok_result.value() << std::endl;
}

if (!err_result)
{
std::cout << "Error code: " << err_result->code << std::endl;
std::cout << "Error code: " << err_result.error().code << std::endl;
}

return 0;
Expand Down
121 changes: 74 additions & 47 deletions include/peelo/result.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020, peelo.net
* Copyright (c) 2020-2024, peelo.net
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
Expand All @@ -24,8 +24,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef PEELO_RESULT_HPP_GUARD
#define PEELO_RESULT_HPP_GUARD
#pragma once

#include <memory>

Expand All @@ -38,85 +37,89 @@ namespace peelo
using value_type = T;
using error_type = E;

enum class type
static inline result<T, E> ok(const value_type& value)
{
ok = 1,
error = 0
};

static inline result<T, E> ok(const T& value)
{
return result(type::ok, new value_type(value), nullptr);
return result(new value_type(value), nullptr);
}

static inline result<T, E> error(const E& error)
static inline result<T, E> error(const error_type& error)
{
return result(type::error, nullptr, new error_type(error));
return result(nullptr, new error_type(error));
}

result(const result& that)
: m_type(that.m_type)
, m_value(that.m_value ? new value_type(*that.m_value) : nullptr)
: m_value(that.m_value ? new value_type(*that.m_value) : nullptr)
, m_error(that.m_error ? new error_type(*that.m_error) : nullptr) {}

template<class T2, class E2>
result(const result<T2, E2>& that)
: m_type(!!that ? type::ok : type::error)
, m_value(that.value() ? new value_type(*that.value()) : nullptr)
, m_error(that.error() ? new error_type(*that.error()) : nullptr) {}
template<class U, class G>
result(const result<U, G>& that)
: m_value(that ? new value_type(that.value()) : nullptr)
, m_error(that ? nullptr : new error_type(that.error())) {}

result& operator=(const result& that)
{
if (this != &that)
{
m_type = that.m_type;
m_value.reset(that.m_value ? new value_type(*that.m_value) : nullptr);
m_error.reset(that.m_error ? new error_type(*that.m_error) : nullptr);
}

return *this;
}

template<class T2, class E2>
result& operator=(const result<T2, E2>& that)
template<class U, class G>
result& operator=(const result<U, G>& that)
{
m_type = !!that ? type::ok : type::error;
m_value.reset(that.value() ? new value_type(*that.value()) : nullptr);
m_error.reset(that.error() ? new error_type(*that.error()) : nullptr);
const auto has_value = that.has_value();

m_value.reset(has_value ? new value_type(that.value()) : nullptr);
m_error.reset(has_value ? nullptr : new error_type(that.error()));

return *this;
}

inline enum type type() const
inline bool has_value() const
{
return m_type;
return !!m_value;
}

inline const std::unique_ptr<value_type>& value() const
inline const value_type& value() const
{
return m_value;
return *m_value;
}

inline const std::unique_ptr<error_type>& error() const
inline const error_type& error() const
{
return m_error;
return *m_error;
}

inline explicit operator bool() const
{
return m_type == type::ok;
return has_value();
}

inline bool operator!() const
{
return m_type == type::error;
return !has_value();
}

inline bool equals(const result& that) const
{
return m_type == that.m_type
&& m_value == that.m_value
&& m_error == that.m_error;
if (has_value())
{
if (!that.has_value())
{
return false;
}

return *m_value == *that.m_value;
}
else if (that.has_value())
{
return false;
}

return *m_error == *that.m_error;
}

inline bool operator==(const result& that) const
Expand All @@ -129,21 +132,45 @@ namespace peelo
return !equals(that);
}

template<class U, class G>
inline bool equals(const result<U, G>& that) const
{
if (has_value())
{
if (!that.has_value())
{
return false;
}

return *m_value == that.value();
}
else if (that.has_value())
{
return false;
}

return *m_error = that.error();
}

template<class U, class G>
inline bool operator==(const result<U, G>& that) const
{
return equals(that);
}

template<class U, class G>
inline bool operator!=(const result<U, G>& that) const
{
return !equals(that);
}

private:
result(
enum type type,
value_type* value,
error_type* error
)
: m_type(type)
, m_value(value)
result(value_type* value, error_type* error)
: m_value(value)
, m_error(error) {}

private:
enum type m_type;
std::unique_ptr<value_type> m_value;
std::unique_ptr<error_type> m_error;
};
}

#endif /* !PEELO_RESULT_HPP_GUARD */
18 changes: 13 additions & 5 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,19 @@ FOREACH(TEST_FILENAME ${TEST_SOURCES})
cxx_std_17
)

TARGET_COMPILE_OPTIONS(
${TEST_NAME}
PRIVATE
-Wall -Werror
)
IF(MSVC)
TARGET_COMPILE_OPTIONS(
${TEST_NAME}
PRIVATE
/W4 /WX
)
ELSE()
TARGET_COMPILE_OPTIONS(
${TEST_NAME}
PRIVATE
-Wall -Werror
)
ENDIF()

TARGET_LINK_LIBRARIES(
${TEST_NAME}
Expand Down
Loading

0 comments on commit b817d51

Please sign in to comment.