66#include < neither/traits.hpp>
77#include < neither/maybe.hpp>
88
9+ #include < neither/traits.hpp>
10+ #include < neither/maybe.hpp>
11+
912namespace neither {
1013
1114template <class T >
@@ -25,7 +28,7 @@ constexpr Left<T> left(T const& x) {
2528
2629template <class T >
2730Left<T> left (T&& x) {
28- return {std::move (x)};
31+ return { std::move (x) };
2932}
3033
3134template <class T >
@@ -41,12 +44,9 @@ constexpr Right<T> right(T const& x) {
4144
4245template <class T >
4346Right<T> right (T&& x) {
44- return {std::move (x)};
47+ return { std::move (x) };
4548}
4649
47-
48-
49-
5050template <class L , class R >
5151struct Either {
5252
@@ -104,18 +104,17 @@ struct Either {
104104 }
105105
106106 constexpr auto left () const -> Maybe<L> {
107- if (! isLeft)
108- return maybe ();
109- return maybe (leftValue );
107+ return isLeft ?
108+ maybe (leftValue) :
109+ maybe ();
110110 }
111111
112112 constexpr auto right () const -> Maybe<R> {
113- if ( isLeft)
114- return maybe ();
115- return maybe (rightValue);
113+ return isLeft ?
114+ maybe () :
115+ maybe (rightValue);
116116 }
117117
118-
119118 static constexpr auto leftOf ( L const & l ) {
120119 return Either<L, R>{ neither::left (l) };
121120 }
@@ -124,7 +123,6 @@ struct Either {
124123 return Either<L, R>{ neither::right (r) };
125124 }
126125
127-
128126 static constexpr auto leftOf ( L && l ) {
129127 return Either<L, R>{ neither::left (std::move (l)) };
130128 }
@@ -133,68 +131,67 @@ struct Either {
133131 return Either<L, R>{ neither::right (std::move (r)) };
134132 }
135133
136-
137134 template <
138135 class L2 = L,
139136 class R2 = R>
140137 constexpr auto join () const
141138 -> decltype(
142- isCopyable (leftValue, rightValue),
139+ isCopyable (( L2 ) leftValue, ( R2 ) rightValue),
143140 std::declval<std::common_type_t<L2, R2>>()
144141 ) {
145- return isLeft? leftValue : rightValue;
142+ return isLeft ? leftValue : rightValue;
146143 }
147144
148-
149145 template <
150146 class L2 = L,
151147 class R2 = R>
152148 auto join ()&&
153149 -> std::common_type_t<L2, R2> {
154- return isLeft? std::move (leftValue) : std::move (rightValue);
150+ return isLeft ? std::move (leftValue) : std::move (rightValue);
155151 }
156152
157153 template <class LeftF , class RightF >
158154 constexpr auto join (LeftF const & leftCase, RightF const & rightCase) const
159155 -> decltype( isLeft? leftCase( leftValue ) : rightCase( rightValue ) ) {
160- return isLeft? leftCase ( leftValue ) : rightCase ( rightValue );
156+ return isLeft ? leftCase ( leftValue ) : rightCase ( rightValue );
161157 }
162158
163- template <class F >
164- constexpr auto leftMap (F const & leftCase) const & -> Either<decltype(leftCase( isCopyable(leftValue, rightValue) )), R> {
165- using NextEither = Either<decltype (leftCase (leftValue)), R>;
159+ template <class F , class L2 =L, class R2 =R>
160+ constexpr auto leftMap (F const & leftCase) const &
161+ -> Either<decltype(leftCase( isCopyable((L2 )leftValue, (R2 )rightValue) )), R2> {
162+ using NextEither = Either<decltype (leftCase (leftValue)), R2 >;
166163 return isLeft ?
167164 NextEither::leftOf ( leftCase ( leftValue ) ) :
168165 NextEither::rightOf ( rightValue );
169166 }
170167
171- template <class F >
172- auto leftMap (F const & leftCase)&& -> Either<decltype(leftCase(std::move(leftValue))), R > {
173- using NextEither = Either<decltype (leftCase (std::move (leftValue))), R >;
168+ template <class F , class L2 =L, class R2 =R >
169+ auto leftMap (F const & leftCase)&& -> Either<decltype(leftCase(std::move(leftValue))), R2 > {
170+ using NextEither = Either<decltype (leftCase (std::move (leftValue))), R2 >;
174171 return isLeft ?
175172 NextEither::leftOf (leftCase (std::move (leftValue))) :
176173 NextEither::rightOf ( std::move (rightValue) );
177174 }
178175
179- template <class F >
180- constexpr auto rightMap (F const & rightCase) const & -> Either<L, decltype(rightCase(isCopyable(rightValue, leftValue)))> {
176+ template <class F , class L2 =L, class R2 =R >
177+ constexpr auto rightMap (F const & rightCase) const & -> Either<L, decltype(rightCase(isCopyable(( R2 ) rightValue, ( L2 ) leftValue)))> {
181178 using NextEither = Either<L, decltype (rightCase (rightValue))>;
182179 return isLeft ?
183180 NextEither::leftOf ( leftValue ) :
184181 NextEither::rightOf ( rightCase ( rightValue ) );
185182 }
186183
187- template <class F >
188- auto rightMap (F const & rightCase)&& -> Either<L , decltype(rightCase(std::move(rightValue)))> {
184+ template <class F , class L2 =L, class R2 =R >
185+ auto rightMap (F const & rightCase)&& -> Either<L2 , decltype(rightCase(std::move(( R2 ) rightValue)))> {
189186 using NextEither = Either<L, decltype (rightCase (std::move (rightValue)))>;
190187 return isLeft ?
191188 NextEither::leftOf ( std::move (leftValue) ) :
192189 NextEither::rightOf ( rightCase ( std::move (rightValue) ) );
193190 }
194191
195- template <class LeftCase >
192+ template <class LeftCase , class L2 =L, class R2 =R >
196193 constexpr auto leftFlatMap (LeftCase const & leftCase) const &
197- -> decltype( ensureEitherRight(leftCase(isCopyable(leftValue)), isCopyable(rightValue))) {
194+ -> decltype( ensureEitherRight(leftCase(isCopyable(( L2 ) leftValue)), isCopyable(( R2 ) rightValue))) {
198195 using NextEither = decltype (leftCase (leftValue));
199196
200197 if (!*this ) {
@@ -204,9 +201,9 @@ struct Either {
204201 return NextEither::rightOf (rightValue);
205202 }
206203
207- template <class RightCase >
204+ template <class RightCase , class L2 = L, class R2 = R >
208205 constexpr auto rightFlatMap (RightCase const & rightCase) const &
209- -> decltype( ensureEitherLeft(rightCase(isCopyable(rightValue)), isCopyable(leftValue))) {
206+ -> decltype( ensureEitherLeft(rightCase(isCopyable(( R2 ) rightValue)), isCopyable(( L2 ) leftValue))) {
210207 using NextEither = decltype (rightCase (rightValue));
211208
212209 if (*this ) {
@@ -216,9 +213,7 @@ struct Either {
216213 return NextEither::leftOf (leftValue);
217214 }
218215
219-
220-
221- template <class LeftCase >
216+ template <class LeftCase , class L2 = L, class R2 = R>
222217 auto leftFlatMap (LeftCase const & leftCase)&&
223218 -> decltype( ensureEitherRight(leftCase(std::move(leftValue)), std::move(rightValue))) {
224219 using NextEither = decltype (leftCase (std::move (leftValue)));
@@ -230,7 +225,7 @@ struct Either {
230225 return NextEither::rightOf (std::move (rightValue));
231226 }
232227
233- template <class RightCase >
228+ template <class RightCase , class L2 =L, class R2 =R >
234229 auto rightFlatMap (RightCase const & rightCase)&&
235230 -> decltype( ensureEitherLeft(rightCase(std::move(rightValue)), std::move(leftValue))) {
236231 using NextEither = decltype (rightCase (std::move (rightValue)));
@@ -245,6 +240,25 @@ struct Either {
245240 constexpr operator bool ()const { return !isLeft; }
246241};
247242
243+ template <typename L, typename R>
244+ bool operator == (Either<L, R> const & a, Either<L, R> const & b) {
245+ if (a.isLeft ) {
246+ if (b.isLeft ) {
247+ return a.left () == b.left ();
248+ }
249+ } else {
250+ if (!b.isLeft ) {
251+ return a.right () == b.right ();
252+ }
253+ }
254+ return false ;
255+ }
256+
257+ template <typename L, typename R>
258+ bool operator != (Either<L, R> const & a, Either<L, R> const & b) {
259+ return !(a == b);
260+ }
261+
248262}
249263
250264#endif
0 commit comments