Skip to content

feat: Pass by-value and then std::move it #69

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 11 commits into
base: master
Choose a base branch
from
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,4 @@

build
.idea
.vscode
16 changes: 8 additions & 8 deletions include/absent/adapters/either/and_then.h
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#ifndef RVARAGO_ABSENT_ADAPTERS_EITHER_ANDTHEN_H
#define RVARAGO_ABSENT_ADAPTERS_EITHER_ANDTHEN_H

#include <utility>

#include "absent/adapters/either/either.h"

#include <utility>

namespace rvarago::absent::adapters::either {

/***
Expand All @@ -19,24 +19,24 @@ namespace rvarago::absent::adapters::either {
* @return a new either containing the mapped value of type B, possibly in error if input was also in error.
*/
template <typename A, typename E, typename UnaryFunction>
constexpr auto and_then(types::either<A, E> const &input,
constexpr auto and_then(types::either<A, E> input,
UnaryFunction &&mapper) noexcept(noexcept(std::declval<UnaryFunction>()(std::declval<A>())))
-> decltype(std::declval<UnaryFunction>()(std::declval<A>())) {
using EitherB = decltype(mapper(std::declval<A>()));
if (auto const p = std::get_if<A>(&input); p) {
return std::forward<UnaryFunction>(mapper)(*p);
if (std::holds_alternative<A>(input)) {
return std::forward<UnaryFunction>(mapper)(std::get<A>(std::move(input)));
}
return EitherB{std::get<E>(input)};
return EitherB{std::get<E>(std::move(input))};
}

/***
* Infix version of and_then.
*/
template <typename A, typename E, typename UnaryFunction>
constexpr auto operator>>(types::either<A, E> const &input,
constexpr auto operator>>(types::either<A, E> input,
UnaryFunction &&mapper) noexcept(noexcept(std::declval<UnaryFunction>()(std::declval<A>())))
-> decltype(std::declval<UnaryFunction>()(std::declval<A>())) {
return and_then(input, std::forward<UnaryFunction>(mapper));
return and_then(std::move(input), std::forward<UnaryFunction>(mapper));
}

}
Expand Down
4 changes: 2 additions & 2 deletions include/absent/adapters/either/attempt.h
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
#ifndef RVARAGO_ABSENT_ADAPTERS_EITHER_ATTEMPT_H
#define RVARAGO_ABSENT_ADAPTERS_EITHER_ATTEMPT_H

#include "absent/adapters/either/either.h"

#include <exception>
#include <utility>

#include "absent/adapters/either/either.h"

namespace rvarago::absent::adapters::either {

/***
Expand Down
8 changes: 4 additions & 4 deletions include/absent/adapters/either/eval.h
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#ifndef RVARAGO_ABSENT_ADAPTERS_EITHER_EVAL_H
#define RVARAGO_ABSENT_ADAPTERS_EITHER_EVAL_H

#include <utility>

#include "absent/adapters/either/either.h"

#include <utility>

namespace rvarago::absent::adapters::either {

/***
Expand All @@ -17,12 +17,12 @@ namespace rvarago::absent::adapters::either {
* @return the wrapped value inside the either or the result of fallback if the either is in error.
*/
template <typename NullaryFunction, typename A, typename E>
constexpr auto eval(types::either<A, E> const &input,
constexpr auto eval(types::either<A, E> input,
NullaryFunction &&fallback) noexcept(noexcept(std::declval<NullaryFunction>()())) -> A {
if (!std::holds_alternative<A>(input)) {
return std::forward<NullaryFunction>(fallback)();
}
return std::get<A>(input);
return std::get<A>(std::move(input));
}

}
Expand Down
10 changes: 5 additions & 5 deletions include/absent/adapters/either/for_each.h
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#ifndef RVARAGO_ABSENT_ADAPTERS_EITHER_FOREACH_H
#define RVARAGO_ABSENT_ADAPTERS_EITHER_FOREACH_H

#include <utility>

#include "absent/adapters/either/either.h"

#include <utility>

namespace rvarago::absent::adapters::either {

/***
Expand All @@ -16,11 +16,11 @@ namespace rvarago::absent::adapters::either {
* @param action an unary function A -> void.
*/
template <typename UnaryFunction, typename A, typename E>
constexpr auto for_each(types::either<A, E> const &input,
constexpr auto for_each(types::either<A, E> input,
UnaryFunction &&action) noexcept(noexcept(std::declval<UnaryFunction>()(std::declval<A>())))
-> void {
if (auto const p = std::get_if<A>(&input); p) {
std::forward<UnaryFunction>(action)(*p);
if (std::holds_alternative<A>(input)) {
std::forward<UnaryFunction>(action)(std::get<A>(std::move(input)));
}
}

Expand Down
16 changes: 8 additions & 8 deletions include/absent/adapters/either/transform.h
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#ifndef RVARAGO_ABSENT_ADAPTERS_EITHER_TRANSFORM_H
#define RVARAGO_ABSENT_ADAPTERS_EITHER_TRANSFORM_H

#include <utility>

#include "absent/adapters/either/either.h"

#include <utility>

namespace rvarago::absent::adapters::either {

/***
Expand All @@ -18,24 +18,24 @@ namespace rvarago::absent::adapters::either {
* @return a new either containing the mapped value of type B, possibly in error if input was also in error.
*/
template <typename A, typename E, typename UnaryFunction>
constexpr auto transform(types::either<A, E> const &input, UnaryFunction &&mapper) noexcept(
constexpr auto transform(types::either<A, E> input, UnaryFunction &&mapper) noexcept(
noexcept(std::forward<UnaryFunction>(mapper)(std::declval<A>())))
-> types::either<decltype(std::declval<UnaryFunction>()(std::declval<A>())), E> {
using B = decltype(mapper(std::declval<A>()));
if (auto const p = std::get_if<A>(&input); p) {
return types::either<B, E>{std::forward<UnaryFunction>(mapper)(*p)};
if (std::holds_alternative<A>(std::move(input))) {
return types::either<B, E>{std::forward<UnaryFunction>(mapper)(std::get<A>(std::move(input)))};
}
return types::either<B, E>{std::get<E>(input)};
return types::either<B, E>{std::get<E>(std::move(input))};
}

/***
* Infix version of transform.
*/
template <typename A, typename E, typename UnaryFunction>
constexpr auto operator|(types::either<A, E> const &input, UnaryFunction &&mapper) noexcept(
constexpr auto operator|(types::either<A, E> input, UnaryFunction &&mapper) noexcept(
noexcept(std::forward<UnaryFunction>(mapper)(std::declval<A>())))
-> types::either<decltype(std::declval<UnaryFunction>()(std::declval<A>())), E> {
return transform(input, std::forward<UnaryFunction>(mapper));
return transform(std::move(input), std::forward<UnaryFunction>(mapper));
}

}
Expand Down
8 changes: 4 additions & 4 deletions include/absent/and_then.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,24 @@ namespace rvarago::absent {
* @return a new nullable generated by mapper, possibly empty if input was also empty.
*/
template <template <typename> typename Nullable, typename UnaryFunction, typename A>
constexpr auto and_then(Nullable<A> const &input,
constexpr auto and_then(Nullable<A> input,
UnaryFunction &&mapper) noexcept(noexcept(std::declval<UnaryFunction>()(std::declval<A>())))
-> decltype(std::declval<UnaryFunction>()(std::declval<A>())) {
using NullableB = decltype(mapper(std::declval<A>()));
if (!input) {
return NullableB{};
}
return std::forward<UnaryFunction>(mapper)(*input);
return std::forward<UnaryFunction>(mapper)(*std::move(input));
}

/***
* Infix version of and_then.
*/
template <template <typename> typename Nullable, typename UnaryFunction, typename A>
constexpr auto operator>>(Nullable<A> const &input,
constexpr auto operator>>(Nullable<A> input,
UnaryFunction &&mapper) noexcept(noexcept(std::declval<UnaryFunction>()(std::declval<A>())))
-> decltype(std::declval<UnaryFunction>()(std::declval<A>())) {
return and_then(input, std::forward<UnaryFunction>(mapper));
return and_then(std::move(input), std::forward<UnaryFunction>(mapper));
}

}
Expand Down
6 changes: 3 additions & 3 deletions include/absent/eval.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ namespace rvarago::absent {
* @return the wrapped value inside the nullable or the result of fallback if the nullable is empty.
*/
template <template <typename> typename Nullable, typename NullaryFunction, typename A>
constexpr auto eval(Nullable<A> const &input,
NullaryFunction &&fallback) noexcept(noexcept(std::declval<NullaryFunction>()())) -> A {
constexpr auto eval(Nullable<A> input, NullaryFunction &&fallback) noexcept(noexcept(std::declval<NullaryFunction>()()))
-> A {
if (!input) {
return std::forward<NullaryFunction>(fallback)();
}
return *input;
return *std::move(input);
}

}
Expand Down
4 changes: 2 additions & 2 deletions include/absent/for_each.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ namespace rvarago::absent {
* @param action an unary function A -> void.
*/
template <template <typename> typename Nullable, typename UnaryFunction, typename A>
constexpr auto for_each(Nullable<A> const &input,
constexpr auto for_each(Nullable<A> input,
UnaryFunction &&action) noexcept(noexcept(std::declval<UnaryFunction>()(std::declval<A>())))
-> void {
if (!input) {
return;
}
std::forward<UnaryFunction>(action)(*input);
std::forward<UnaryFunction>(action)(*std::move(input));
}

}
Expand Down
10 changes: 5 additions & 5 deletions include/absent/support/from_variant.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ namespace rvarago::absent {
*/
template <typename A, template <typename> typename Nullable = std::optional, typename... Rest>
constexpr auto from_variant(std::variant<Rest...> v) noexcept -> Nullable<A> {
static_assert(std::disjunction_v<std::is_same<A, Rest>...>, "The provided type A is not a member of the variant.");

if (auto const value = std::get_if<A>(&v); value) {
return Nullable<A>{*value};
static_assert(std::disjunction_v<std::is_same<A, Rest>...>, "A is not a member type of the variant");
if (std::holds_alternative<A>(v)) {
return Nullable<A>{std::get<A>(std::move(v))};
} else {
return Nullable<A>{};
}
return Nullable<A>{};
}

}
Expand Down
8 changes: 4 additions & 4 deletions include/absent/transform.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,24 @@ namespace rvarago::absent {
* @return a new nullable containing the mapped value of type B, possibly empty if input was also empty.
*/
template <template <typename> typename Nullable, typename A, typename UnaryFunction>
constexpr auto transform(Nullable<A> const &input,
constexpr auto transform(Nullable<A> input,
UnaryFunction &&mapper) noexcept(noexcept(std::declval<UnaryFunction>()(std::declval<A>())))
-> Nullable<decltype(std::declval<UnaryFunction>()(std::declval<A>()))> {
using B = decltype(mapper(std::declval<A>()));
if (!input) {
return Nullable<B>{};
}
return Nullable<B>{std::forward<UnaryFunction>(mapper)(*input)};
return Nullable<B>{std::forward<UnaryFunction>(mapper)(*std::move(input))};
}

/***
* Infix version of transform.
*/
template <template <typename> typename Nullable, typename A, typename UnaryFunction>
constexpr auto operator|(Nullable<A> const &input,
constexpr auto operator|(Nullable<A> input,
UnaryFunction &&mapper) noexcept(noexcept(std::declval<UnaryFunction>()(std::declval<A>())))
-> Nullable<decltype(std::declval<UnaryFunction>()(std::declval<A>()))> {
return transform(input, std::forward<UnaryFunction>(mapper));
return transform(std::move(input), std::forward<UnaryFunction>(mapper));
}

}
Expand Down