13 #include <type_traits>
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.");
35 explicit Either (
const L& l)
40 explicit Either (
const R& r)
52 return This_.index () == LeftVal;
57 return This_.index () == RightVal;
63 throw std::runtime_error {
"Tried accessing Left for a Right Either" };
64 return std::get<L> (This_);
70 throw std::runtime_error {
"Tried accessing Right for a Left Either" };
71 return std::get<R> (This_);
101 template<
typename RNew>
119 template<
typename... Vars>
122 return Either { std::visit ([] (
auto&& arg) {
return L { std::forward<decltype (arg)> (arg) }; }, var) };
125 template<
typename... Vars>
129 Right (either.GetRight ()) :
133 template<
typename LPrime,
typename = std::enable_if_t<std::is_convertible_v<LPrime, L>>>
136 return either.IsRight () ?
137 Right (either.GetRight ()) :
141 template<
typename RNew>
142 static std::enable_if_t<!std::is_convertible<RNew, R>::value,
Either<L, RNew>>
Right (
const RNew& r)
149 return [] (
const auto& other)
151 static_assert (std::is_convertible<std::decay_t<decltype (other.GetLeft ())>, L>::value,
152 "Other's Either's Left type is not convertible to this Left type.");
153 return other.IsLeft () ?
161 return e1.This_ == e2.This_;
170 template<
typename L,
typename R,
typename F,
typename = std::result_of_t<F ()>>
171 R
RightOr (
const Either<L, R>& either, F&&
f)
173 return either.IsRight () ?
178 template<
typename L,
typename R>
181 return either.IsRight () ?
186 template<
template<
typename>
class Cont,
typename L,
typename R>
187 std::pair<Cont<L>, Cont<R>>
PartitionEithers (
const Cont<Either<L, R>>& eithers)
189 std::pair<Cont<L>, Cont<R>> result;
190 for (
const auto& either : eithers)
191 if (either.IsLeft ())
192 result.first.push_back (either.GetLeft ());
194 result.second.push_back (either.GetRight ());
199 template<
typename Left,
typename Right,
typename... Args>
202 return Visit (either.AsVariant (), std::forward<Args> (args)...);