Skip to content

Commit

Permalink
Made Result::ValueWrapper constructors explicit
Browse files Browse the repository at this point in the history
  • Loading branch information
abbyssoul committed Sep 25, 2019
1 parent 87a75d8 commit b58b81b
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 71 deletions.
138 changes: 69 additions & 69 deletions include/solace/result.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,11 @@ template<typename T, typename Tag>
struct ValueWrapper {
using value_type = T;

constexpr ValueWrapper(value_type const& val) noexcept(std::is_nothrow_copy_constructible<value_type>::value)
explicit constexpr ValueWrapper(value_type const& val) noexcept(std::is_nothrow_copy_constructible<value_type>::value)
: val_{val}
{ }

constexpr ValueWrapper(value_type&& val) noexcept(std::is_nothrow_move_constructible<value_type>::value)
explicit constexpr ValueWrapper(value_type&& val) noexcept(std::is_nothrow_move_constructible<value_type>::value)
: val_{mv(val)}
{ }

Expand Down Expand Up @@ -199,17 +199,17 @@ class
// [[nodiscard]]
Result {
public:
using value_type = V;
using error_type = E;
using value_type = V;
using error_type = E;

static_assert(!std::is_same<E, void>::value,
"Error type must be non-void");
static_assert(!std::is_same<E, void>::value,
"Error type must be non-void");

public:

inline ~Result() {
destroy();
}
inline ~Result() {
destroy();
}

/** Copy construct of Result is disabled */
Result(Result const& rhs) = delete;
Expand All @@ -221,47 +221,44 @@ Result {
*/
Result(Result&& rhs) noexcept(std::is_nothrow_move_constructible<V>::value &&
std::is_nothrow_move_constructible<E>::value)
: _engaged {
rhs.isOk()
? emplaceValue(mv(rhs._value))
: emplaceError(mv(rhs._error))
}
{
}
: _engaged(rhs.isOk() ? emplaceValue(mv(rhs._value)) : emplaceError(mv(rhs._error)))
{}

template<typename DV,
typename x = typename std::enable_if_t<std::is_constructible_v<V, DV>, DV>
>
Result(Result<DV, E>&& rhs) noexcept
: _engaged {
rhs.isOk()
? emplaceValue(mv(rhs._value))
: emplaceError(mv(rhs._error))
}
: _engaged(rhs.isOk() ? emplaceValue(mv(rhs._value)) : emplaceError(mv(rhs._error)))
{
}

Result& operator= (Result&& rhs) noexcept {
return swap(rhs);
}
Result& operator= (Result&& rhs) noexcept {
return swap(rhs);
}


/**
* Move-Construct Ok result
* @param value Ok value to move from
*/
explicit constexpr Result(types::Ok<V>&& value) noexcept(std::is_nothrow_move_constructible<V>::value)
template<typename DV,
typename x = typename std::enable_if_t<std::is_constructible_v<V, DV>, DV>
>
constexpr Result(types::Ok<DV>&& value) noexcept(std::is_nothrow_move_constructible<V>::value)
: Result{types::okTag, mv(value.val_)}
{}
{}


/**
* Move-Construct Err result by moving error value
* @param err Err value to move from
*/
explicit constexpr Result(types::Err<E>&& value) noexcept(std::is_nothrow_move_constructible<E>::value)
template<typename DE,
typename x = typename std::enable_if_t<std::is_constructible_v<E, DE>, DE>
>
constexpr Result(types::Err<DE>&& value) noexcept(std::is_nothrow_move_constructible<E>::value)
: Result{types::errTag, mv(value.val_)}
{}
{}

/**
* Move-Construct Err result from a compatible error type by moving error value
Expand All @@ -270,7 +267,7 @@ Result {
template<typename VW, typename Tag>
constexpr Result(types::ValueWrapper<VW, Tag>&& value) // Can't say much about noexcept
: Result{Tag{}, mv(value.val_)}
{}
{}


template<typename CanBeV>
Expand Down Expand Up @@ -299,47 +296,37 @@ Result {
, _engaged{false}
{}


template<typename TE,
typename T = typename std::enable_if_t<!std::is_same_v<V, E>
&& std::is_constructible_v<E, TE>,
TE>
>
constexpr Result(TE&& value)
: _error{fwd<TE>(value)}
, _engaged{false}
template<typename X>
constexpr Result(X&& value)
: _engaged{tryEngade(fwd<X>(value))}
{}

public:

Result& swap(Result& rhs) noexcept {
using std::swap;
Result& swap(Result& rhs) noexcept {
using std::swap;

if (isOk()) {
StoredValue_type v{mv(_value)};
if (rhs.isOk()) {
constructValue(mv(rhs._value));
} else {
constructError(mv(rhs._error));
}
rhs.constructValue(mv(v));

} else {
StoredError_type e{mv(_error)};
if (rhs.isOk()) {
constructValue(mv(rhs._value));
} else {
constructError(mv(rhs._error));
}
rhs.constructError(mv(e));
}

if (isOk()) {
if (rhs.isOk()) {
StoredValue_type v(mv(_value));
constructValue(mv(rhs._value));
rhs.constructValue(mv(v));
} else {
StoredValue_type v(mv(_value));
constructError(mv(rhs._error));
rhs.constructValue(mv(v));
}

} else {
if (rhs.isOk()) {
StoredValue_type v(mv(rhs._value));
rhs.constructError(mv(_error));
constructValue(mv(v));
} else {
StoredError_type v(mv(_error));
constructError(mv(rhs._error));
rhs.constructError(mv(v));
}
}

return (*this);
}
return (*this);
}

explicit operator bool () const noexcept {
return isOk();
Expand Down Expand Up @@ -593,22 +580,35 @@ Result {

private:

template<typename X>
bool tryEngade(X&& value) {
if constexpr (std::is_constructible_v<E, X>) {
return emplaceError(fwd<X>(value));
} else {
return emplaceValue(fwd<X>(value));
}
}

template<typename DV, typename DE>
friend class Result;

using mutable_value = std::remove_const_t<value_type>;
using mutable_value = std::remove_cv_t<value_type>;
using StoredValue_type = std::conditional_t<std::is_reference_v<value_type>,
std::reference_wrapper<std::remove_reference_t<mutable_value>>,
std::reference_wrapper<std::decay_t<value_type>>,
mutable_value>;

using StoredError_type = std::remove_const_t<E>;

using mutable_error = std::remove_cv_t<error_type>;
using StoredError_type = std::conditional_t<std::is_reference_v<error_type>,
std::reference_wrapper<std::decay_t<error_type>>,
mutable_error>;

union {
StoredValue_type _value;
StoredError_type _error;
};

bool _engaged = false;
bool _engaged{false};
};


Expand Down
32 changes: 32 additions & 0 deletions include/solace/stringView.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,38 @@ bool operator!= (StringView lhv, StringView rhv) noexcept {
return !lhv.equals(rhv);
}

inline
bool operator== (StringLiteral lhv, StringView rhv) noexcept {
return lhv.equals(rhv);
}

inline
bool operator!= (StringLiteral lhv, StringView rhv) noexcept {
return !lhv.equals(rhv);
}

inline
bool operator== (StringView lhv, StringLiteral rhv) noexcept {
return lhv.equals(rhv);
}

inline
bool operator!= (StringView lhv, StringLiteral rhv) noexcept {
return !lhv.equals(rhv);
}


inline
bool operator== (StringLiteral lhv, StringLiteral rhv) noexcept {
return lhv.equals(rhv);
}

inline
bool operator!= (StringLiteral lhv, StringLiteral rhv) noexcept {
return !lhv.equals(rhv);
}


inline
bool operator== (char const* rhv, StringView str) noexcept {
return str.equals(rhv);
Expand Down
2 changes: 1 addition & 1 deletion src/string.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ Solace::makeString(StringView str) {
return writeResult.moveError();
}

return Ok(String{maybeBuffer.moveResult(), str.size()});
return Ok(String{ maybeBuffer.moveResult(), str.size() });
}


Expand Down
28 changes: 27 additions & 1 deletion test/test_result.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,31 @@ TEST_F(TestResult, dereferencingErrThrows) {
EXPECT_THROW(*v, Exception);
}

TEST_F(TestResult, testSwap) {
Result<MoveOnlyType, SimpleType> v1{types::errTag, in_place, 112, 2, -1};
Result<MoveOnlyType, SimpleType> v2{types::okTag, in_place, 42};

ASSERT_EQ(1, SimpleType::InstanceCount);
ASSERT_EQ(1, MoveOnlyType::InstanceCount);

ASSERT_TRUE(v1.isError());
ASSERT_TRUE(v2.isOk());

ASSERT_EQ(112, v1.getError().x);
ASSERT_EQ(42, v2.unwrap().x_);

v1.swap(v2);

EXPECT_TRUE(v1.isOk());
EXPECT_TRUE(v2.isError());

EXPECT_EQ(112, v2.getError().x);
EXPECT_EQ(42, v1.unwrap().x_);

EXPECT_EQ(1, SimpleType::InstanceCount);
EXPECT_EQ(1, MoveOnlyType::InstanceCount);
}


TEST_F(TestResult, testVoidResult) {
Result<void, int> v = Ok();
Expand Down Expand Up @@ -689,8 +714,9 @@ TEST_F(TestResult, test_inpace_construtor) {

TEST_F(TestResult, testRefTypesResult) {
SimpleType value{3, 2, 1};
SimpleType& valueRef = value;

Result<SimpleType&, PimitiveType> res{types::okTag, value};
Result<SimpleType&, PimitiveType> res{types::okTag, valueRef};
ASSERT_TRUE(res.isOk());
EXPECT_TRUE(value.InstanceCount = 1);

Expand Down

0 comments on commit b58b81b

Please sign in to comment.