20 template<
typename L,
typename R>
23 using Either_t = std::variant<L, R>;
26 enum { LeftVal, RightVal };
28 static_assert (!std::is_same<L, R>::value,
"Types cannot be the same.");
41 : This_ {
std::move (r) }
57 return This_.index () == LeftVal;
62 return This_.index () == RightVal;
68 throw std::runtime_error {
"Tried accessing Left for a Right Either" };
69 return std::get<L> (This_);
75 throw std::runtime_error {
"Tried accessing Right for a Left Either" };
76 return std::get<R> (This_);
100 return std::move (This_);
111 template<
typename RNew>
126 return Either { std::move (r) };
134 template<
typename... Vars>
137 return Either { std::visit ([] (
auto&& arg) {
return L { std::forward<decltype (arg)> (arg) }; }, var) };
140 template<
typename... Vars>
144 Right (either.GetRight ()) :
148 template<
typename LPrime,
typename = std::enable_if_t<std::is_convertible_v<LPrime, L>>>
151 return either.IsRight () ?
152 Right (either.GetRight ()) :
153 Left (either.GetLeft ());
156 template<
typename RNew>
164 return [] (
const auto& other)
166 static_assert (std::is_convertible<std::decay_t<
decltype (other.GetLeft ())>, L>::value,
167 "Other's Either's Left type is not convertible to this Left type.");
168 return other.IsLeft () ?
176 return e1.This_ == e2.This_;
185 template<
typename L,
typename R,
typename F,
typename = std::result_of_t<F ()>>
188 return either.IsRight () ?
193 template<
typename L,
typename R>
196 return either.IsRight () ?
201 template<
template<
typename>
class Cont,
typename L,
typename R>
204 std::pair<Cont<L>, Cont<R>> result;
205 for (
const auto& either : eithers)
206 if (either.IsLeft ())
207 result.first.push_back (either.GetLeft ());
209 result.second.push_back (either.GetRight ());
214 template<
typename Left,
typename Right,
typename... Args>
217 return Visit (either.AsVariant (), std::forward<Args> (args)...);
220 template<
typename Left,
typename Right,
typename... Args>
223 return Visit (std::move (either).AsVariant (), std::forward<Args> (args)...);
static Either< L, RNew > FromMaybe(const std::optional< RNew > &maybeRight, const L &left)
friend bool operator!=(const Either &e1, const Either &e2)
Either & operator=(const Either &)=default
const R & GetRight() const
static Either LeftLift(const std::variant< Vars... > &var)
std::variant< L, R > AsVariant() const &
std::variant< L, R > AsVariant() &&
static Either Left(const L &l)
std::optional< L > MaybeLeft() const
const L & GetLeft() const
static Either Right(R &&r)
static Either Right(const R &r)
static Either LeftLift(const Either< std::variant< Vars... >, R > &either)
friend bool operator==(const Either &e1, const Either &e2)
static auto EmbeddingLeft()
static Either LeftLift(const Either< LPrime, R > &either)
Either(Either &&)=default
static std::enable_if_t<!std::is_convertible< RNew, R >::value, Either< L, RNew > > Right(const RNew &r)
std::optional< R > MaybeRight() const
Either(const Either &)=default
auto Visit(const Either< Left, Right > &either, Args &&... args)
std::pair< Cont< L >, Cont< R > > PartitionEithers(const Cont< Either< L, R > > &eithers)
R RightOr(const Either< L, R > &either, F &&f)