Skip to content

Commit 9e60886

Browse files
feat: Add binary operation/apply cross-type overload of the binary version
1 parent 691a913 commit 9e60886

1 file changed

Lines changed: 273 additions & 0 deletions

File tree

src/operations/operators.cppm

Lines changed: 273 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
module;
22

33
#include <compare>
4+
#include <concepts>
45
#include <expected>
56
#include <type_traits>
67
#include <utility>
@@ -67,6 +68,21 @@ using primitive_dispatch_result_t = std::expected<meta::make_primitive_t<
6768
typename meta::traits<Lhs>::policies>,
6869
ErrorPayload>;
6970

71+
template <typename T>
72+
concept underlying_operand = underlying_type<std::remove_cvref_t<T>>;
73+
74+
template <primitive_instance Primitive, underlying_operand Underlying>
75+
using mixed_bridge_primitive_t = meta::make_primitive_t<
76+
std::remove_cvref_t<Underlying>, typename meta::traits<Primitive>::policies>;
77+
78+
template <operation OpTag, primitive_instance Primitive,
79+
underlying_operand Underlying,
80+
typename ErrorPayload = policy::error::kind>
81+
using mixed_primitive_dispatch_result_t =
82+
primitive_dispatch_result_t<OpTag, Primitive,
83+
mixed_bridge_primitive_t<Primitive, Underlying>,
84+
ErrorPayload>;
85+
7086
template <primitive_instance Lhs, primitive_instance Rhs,
7187
typename ErrorPayload = policy::error::kind>
7288
using three_way_dispatch_result_t = std::expected<
@@ -75,6 +91,25 @@ using three_way_dispatch_result_t = std::expected<
7591
ErrorPayload>::common_rep>,
7692
ErrorPayload>;
7793

94+
template <primitive_instance Primitive, underlying_operand Underlying,
95+
typename ErrorPayload = policy::error::kind>
96+
using mixed_three_way_dispatch_result_t =
97+
three_way_dispatch_result_t<Primitive,
98+
mixed_bridge_primitive_t<Primitive, Underlying>,
99+
ErrorPayload>;
100+
101+
template <operation OpTag, underlying_operand Underlying,
102+
primitive_instance Primitive,
103+
typename ErrorPayload = policy::error::kind>
104+
using flipped_mixed_primitive_dispatch_result_t = primitive_dispatch_result_t<
105+
OpTag, mixed_bridge_primitive_t<Primitive, Underlying>, Primitive,
106+
ErrorPayload>;
107+
108+
template <underlying_operand Underlying, primitive_instance Primitive,
109+
typename ErrorPayload = policy::error::kind>
110+
using flipped_mixed_three_way_dispatch_result_t = three_way_dispatch_result_t<
111+
mixed_bridge_primitive_t<Primitive, Underlying>, Primitive, ErrorPayload>;
112+
78113
template <operation OpTag, primitive_instance Lhs, primitive_instance Rhs,
79114
typename ErrorPayload = policy::error::kind>
80115
constexpr auto apply(Lhs const &lhs, Rhs const &rhs)
@@ -91,48 +126,158 @@ constexpr auto apply(Lhs const &lhs, Rhs const &rhs)
91126
return result_primitive{*raw};
92127
}
93128

129+
template <operation OpTag, primitive_instance Lhs, underlying_operand Rhs,
130+
typename ErrorPayload = policy::error::kind>
131+
constexpr auto apply(Lhs const &lhs, Rhs const &rhs)
132+
-> mixed_primitive_dispatch_result_t<OpTag, Lhs, Rhs, ErrorPayload> {
133+
using bridge_rhs_t = mixed_bridge_primitive_t<Lhs, Rhs>;
134+
auto const bridge_rhs = bridge_rhs_t{rhs};
135+
return apply<OpTag, Lhs, bridge_rhs_t, ErrorPayload>(lhs, bridge_rhs);
136+
}
137+
138+
template <operation OpTag, underlying_operand Lhs, primitive_instance Rhs,
139+
typename ErrorPayload = policy::error::kind>
140+
constexpr auto apply(Lhs const &lhs, Rhs const &rhs)
141+
-> flipped_mixed_primitive_dispatch_result_t<OpTag, Lhs, Rhs,
142+
ErrorPayload> {
143+
using bridge_lhs_t = mixed_bridge_primitive_t<Rhs, Lhs>;
144+
auto const bridge_lhs = bridge_lhs_t{lhs};
145+
return apply<OpTag, bridge_lhs_t, Rhs, ErrorPayload>(bridge_lhs, rhs);
146+
}
147+
94148
template <primitive_instance Lhs, primitive_instance Rhs,
95149
typename ErrorPayload = policy::error::kind>
96150
constexpr auto add(Lhs const &lhs, Rhs const &rhs)
97151
-> primitive_dispatch_result_t<Addition, Lhs, Rhs, ErrorPayload> {
98152
return apply<Addition, Lhs, Rhs, ErrorPayload>(lhs, rhs);
99153
}
100154

155+
template <primitive_instance Lhs, underlying_operand Rhs,
156+
typename ErrorPayload = policy::error::kind>
157+
constexpr auto add(Lhs const &lhs, Rhs const &rhs)
158+
-> mixed_primitive_dispatch_result_t<Addition, Lhs, Rhs, ErrorPayload> {
159+
return apply<Addition, Lhs, Rhs, ErrorPayload>(lhs, rhs);
160+
}
161+
162+
template <underlying_operand Lhs, primitive_instance Rhs,
163+
typename ErrorPayload = policy::error::kind>
164+
constexpr auto add(Lhs const &lhs, Rhs const &rhs)
165+
-> flipped_mixed_primitive_dispatch_result_t<Addition, Lhs, Rhs,
166+
ErrorPayload> {
167+
return apply<Addition, Lhs, Rhs, ErrorPayload>(lhs, rhs);
168+
}
169+
101170
template <primitive_instance Lhs, primitive_instance Rhs,
102171
typename ErrorPayload = policy::error::kind>
103172
constexpr auto sub(Lhs const &lhs, Rhs const &rhs)
104173
-> primitive_dispatch_result_t<Subtraction, Lhs, Rhs, ErrorPayload> {
105174
return apply<Subtraction, Lhs, Rhs, ErrorPayload>(lhs, rhs);
106175
}
107176

177+
template <primitive_instance Lhs, underlying_operand Rhs,
178+
typename ErrorPayload = policy::error::kind>
179+
constexpr auto sub(Lhs const &lhs, Rhs const &rhs)
180+
-> mixed_primitive_dispatch_result_t<Subtraction, Lhs, Rhs, ErrorPayload> {
181+
return apply<Subtraction, Lhs, Rhs, ErrorPayload>(lhs, rhs);
182+
}
183+
184+
template <underlying_operand Lhs, primitive_instance Rhs,
185+
typename ErrorPayload = policy::error::kind>
186+
constexpr auto sub(Lhs const &lhs, Rhs const &rhs)
187+
-> flipped_mixed_primitive_dispatch_result_t<Subtraction, Lhs, Rhs,
188+
ErrorPayload> {
189+
return apply<Subtraction, Lhs, Rhs, ErrorPayload>(lhs, rhs);
190+
}
191+
108192
template <primitive_instance Lhs, primitive_instance Rhs,
109193
typename ErrorPayload = policy::error::kind>
110194
constexpr auto mul(Lhs const &lhs, Rhs const &rhs)
111195
-> primitive_dispatch_result_t<Multiplication, Lhs, Rhs, ErrorPayload> {
112196
return apply<Multiplication, Lhs, Rhs, ErrorPayload>(lhs, rhs);
113197
}
114198

199+
template <primitive_instance Lhs, underlying_operand Rhs,
200+
typename ErrorPayload = policy::error::kind>
201+
constexpr auto mul(Lhs const &lhs, Rhs const &rhs)
202+
-> mixed_primitive_dispatch_result_t<Multiplication, Lhs, Rhs,
203+
ErrorPayload> {
204+
return apply<Multiplication, Lhs, Rhs, ErrorPayload>(lhs, rhs);
205+
}
206+
207+
template <underlying_operand Lhs, primitive_instance Rhs,
208+
typename ErrorPayload = policy::error::kind>
209+
constexpr auto mul(Lhs const &lhs, Rhs const &rhs)
210+
-> flipped_mixed_primitive_dispatch_result_t<Multiplication, Lhs, Rhs,
211+
ErrorPayload> {
212+
return apply<Multiplication, Lhs, Rhs, ErrorPayload>(lhs, rhs);
213+
}
214+
115215
template <primitive_instance Lhs, primitive_instance Rhs,
116216
typename ErrorPayload = policy::error::kind>
117217
constexpr auto div(Lhs const &lhs, Rhs const &rhs)
118218
-> primitive_dispatch_result_t<Division, Lhs, Rhs, ErrorPayload> {
119219
return apply<Division, Lhs, Rhs, ErrorPayload>(lhs, rhs);
120220
}
121221

222+
template <primitive_instance Lhs, underlying_operand Rhs,
223+
typename ErrorPayload = policy::error::kind>
224+
constexpr auto div(Lhs const &lhs, Rhs const &rhs)
225+
-> mixed_primitive_dispatch_result_t<Division, Lhs, Rhs, ErrorPayload> {
226+
return apply<Division, Lhs, Rhs, ErrorPayload>(lhs, rhs);
227+
}
228+
229+
template <underlying_operand Lhs, primitive_instance Rhs,
230+
typename ErrorPayload = policy::error::kind>
231+
constexpr auto div(Lhs const &lhs, Rhs const &rhs)
232+
-> flipped_mixed_primitive_dispatch_result_t<Division, Lhs, Rhs,
233+
ErrorPayload> {
234+
return apply<Division, Lhs, Rhs, ErrorPayload>(lhs, rhs);
235+
}
236+
122237
template <primitive_instance Lhs, primitive_instance Rhs,
123238
typename ErrorPayload = policy::error::kind>
124239
constexpr auto equal(Lhs const &lhs, Rhs const &rhs)
125240
-> primitive_dispatch_result_t<Equal, Lhs, Rhs, ErrorPayload> {
126241
return apply<Equal, Lhs, Rhs, ErrorPayload>(lhs, rhs);
127242
}
128243

244+
template <primitive_instance Lhs, underlying_operand Rhs,
245+
typename ErrorPayload = policy::error::kind>
246+
constexpr auto equal(Lhs const &lhs, Rhs const &rhs)
247+
-> mixed_primitive_dispatch_result_t<Equal, Lhs, Rhs, ErrorPayload> {
248+
return apply<Equal, Lhs, Rhs, ErrorPayload>(lhs, rhs);
249+
}
250+
251+
template <underlying_operand Lhs, primitive_instance Rhs,
252+
typename ErrorPayload = policy::error::kind>
253+
constexpr auto equal(Lhs const &lhs, Rhs const &rhs)
254+
-> flipped_mixed_primitive_dispatch_result_t<Equal, Lhs, Rhs,
255+
ErrorPayload> {
256+
return apply<Equal, Lhs, Rhs, ErrorPayload>(lhs, rhs);
257+
}
258+
129259
template <primitive_instance Lhs, primitive_instance Rhs,
130260
typename ErrorPayload = policy::error::kind>
131261
constexpr auto not_equal(Lhs const &lhs, Rhs const &rhs)
132262
-> primitive_dispatch_result_t<NotEqual, Lhs, Rhs, ErrorPayload> {
133263
return apply<NotEqual, Lhs, Rhs, ErrorPayload>(lhs, rhs);
134264
}
135265

266+
template <primitive_instance Lhs, underlying_operand Rhs,
267+
typename ErrorPayload = policy::error::kind>
268+
constexpr auto not_equal(Lhs const &lhs, Rhs const &rhs)
269+
-> mixed_primitive_dispatch_result_t<NotEqual, Lhs, Rhs, ErrorPayload> {
270+
return apply<NotEqual, Lhs, Rhs, ErrorPayload>(lhs, rhs);
271+
}
272+
273+
template <underlying_operand Lhs, primitive_instance Rhs,
274+
typename ErrorPayload = policy::error::kind>
275+
constexpr auto not_equal(Lhs const &lhs, Rhs const &rhs)
276+
-> flipped_mixed_primitive_dispatch_result_t<NotEqual, Lhs, Rhs,
277+
ErrorPayload> {
278+
return apply<NotEqual, Lhs, Rhs, ErrorPayload>(lhs, rhs);
279+
}
280+
136281
template <primitive_instance Lhs, primitive_instance Rhs,
137282
typename ErrorPayload = policy::error::kind>
138283
constexpr auto three_way_compare(Lhs const &lhs, Rhs const &rhs)
@@ -151,6 +296,24 @@ constexpr auto three_way_compare(Lhs const &lhs, Rhs const &rhs)
151296
return details::decode_three_way_code<ordering, common_rep>(*raw);
152297
}
153298

299+
template <primitive_instance Lhs, underlying_operand Rhs,
300+
typename ErrorPayload = policy::error::kind>
301+
constexpr auto three_way_compare(Lhs const &lhs, Rhs const &rhs)
302+
-> mixed_three_way_dispatch_result_t<Lhs, Rhs, ErrorPayload> {
303+
using bridge_rhs_t = mixed_bridge_primitive_t<Lhs, Rhs>;
304+
auto const bridge_rhs = bridge_rhs_t{rhs};
305+
return three_way_compare<Lhs, bridge_rhs_t, ErrorPayload>(lhs, bridge_rhs);
306+
}
307+
308+
template <underlying_operand Lhs, primitive_instance Rhs,
309+
typename ErrorPayload = policy::error::kind>
310+
constexpr auto three_way_compare(Lhs const &lhs, Rhs const &rhs)
311+
-> flipped_mixed_three_way_dispatch_result_t<Lhs, Rhs, ErrorPayload> {
312+
using bridge_lhs_t = mixed_bridge_primitive_t<Rhs, Lhs>;
313+
auto const bridge_lhs = bridge_lhs_t{lhs};
314+
return three_way_compare<bridge_lhs_t, Rhs, ErrorPayload>(bridge_lhs, rhs);
315+
}
316+
154317
template <operation OpTag, primitive_instance Lhs, primitive_instance Rhs,
155318
typename ErrorPayload = policy::error::kind>
156319
constexpr auto apply_assign(Lhs &lhs, Rhs const &rhs)
@@ -223,6 +386,22 @@ constexpr auto operator+(Lhs const &lhs, Rhs const &rhs)
223386
return operations::add(lhs, rhs);
224387
}
225388

389+
template <operations::primitive_instance Lhs,
390+
operations::underlying_operand Rhs>
391+
constexpr auto operator+(Lhs const &lhs, Rhs const &rhs)
392+
-> operations::mixed_primitive_dispatch_result_t<operations::Addition, Lhs,
393+
Rhs> {
394+
return operations::add(lhs, rhs);
395+
}
396+
397+
template <operations::underlying_operand Lhs,
398+
operations::primitive_instance Rhs>
399+
constexpr auto operator+(Lhs const &lhs, Rhs const &rhs)
400+
-> operations::flipped_mixed_primitive_dispatch_result_t<
401+
operations::Addition, Lhs, Rhs> {
402+
return operations::add(lhs, rhs);
403+
}
404+
226405
template <operations::primitive_instance Lhs,
227406
operations::primitive_instance Rhs>
228407
constexpr auto operator-(Lhs const &lhs, Rhs const &rhs)
@@ -231,6 +410,22 @@ constexpr auto operator-(Lhs const &lhs, Rhs const &rhs)
231410
return operations::sub(lhs, rhs);
232411
}
233412

413+
template <operations::primitive_instance Lhs,
414+
operations::underlying_operand Rhs>
415+
constexpr auto operator-(Lhs const &lhs, Rhs const &rhs)
416+
-> operations::mixed_primitive_dispatch_result_t<operations::Subtraction,
417+
Lhs, Rhs> {
418+
return operations::sub(lhs, rhs);
419+
}
420+
421+
template <operations::underlying_operand Lhs,
422+
operations::primitive_instance Rhs>
423+
constexpr auto operator-(Lhs const &lhs, Rhs const &rhs)
424+
-> operations::flipped_mixed_primitive_dispatch_result_t<
425+
operations::Subtraction, Lhs, Rhs> {
426+
return operations::sub(lhs, rhs);
427+
}
428+
234429
template <operations::primitive_instance Lhs,
235430
operations::primitive_instance Rhs>
236431
constexpr auto operator*(Lhs const &lhs, Rhs const &rhs)
@@ -239,34 +434,112 @@ constexpr auto operator*(Lhs const &lhs, Rhs const &rhs)
239434
return operations::mul(lhs, rhs);
240435
}
241436

437+
template <operations::primitive_instance Lhs,
438+
operations::underlying_operand Rhs>
439+
constexpr auto operator*(Lhs const &lhs, Rhs const &rhs)
440+
-> operations::mixed_primitive_dispatch_result_t<operations::Multiplication,
441+
Lhs, Rhs> {
442+
return operations::mul(lhs, rhs);
443+
}
444+
445+
template <operations::underlying_operand Lhs,
446+
operations::primitive_instance Rhs>
447+
constexpr auto operator*(Lhs const &lhs, Rhs const &rhs)
448+
-> operations::flipped_mixed_primitive_dispatch_result_t<
449+
operations::Multiplication, Lhs, Rhs> {
450+
return operations::mul(lhs, rhs);
451+
}
452+
242453
template <operations::primitive_instance Lhs,
243454
operations::primitive_instance Rhs>
244455
constexpr auto operator/(Lhs const &lhs, Rhs const &rhs)
245456
-> operations::primitive_dispatch_result_t<operations::Division, Lhs, Rhs> {
246457
return operations::div(lhs, rhs);
247458
}
248459

460+
template <operations::primitive_instance Lhs,
461+
operations::underlying_operand Rhs>
462+
constexpr auto operator/(Lhs const &lhs, Rhs const &rhs)
463+
-> operations::mixed_primitive_dispatch_result_t<operations::Division, Lhs,
464+
Rhs> {
465+
return operations::div(lhs, rhs);
466+
}
467+
468+
template <operations::underlying_operand Lhs,
469+
operations::primitive_instance Rhs>
470+
constexpr auto operator/(Lhs const &lhs, Rhs const &rhs)
471+
-> operations::flipped_mixed_primitive_dispatch_result_t<
472+
operations::Division, Lhs, Rhs> {
473+
return operations::div(lhs, rhs);
474+
}
475+
249476
template <operations::primitive_instance Lhs,
250477
operations::primitive_instance Rhs>
251478
constexpr auto operator==(Lhs const &lhs, Rhs const &rhs)
252479
-> operations::primitive_dispatch_result_t<operations::Equal, Lhs, Rhs> {
253480
return operations::equal(lhs, rhs);
254481
}
255482

483+
template <operations::primitive_instance Lhs,
484+
operations::underlying_operand Rhs>
485+
constexpr auto operator==(Lhs const &lhs, Rhs const &rhs)
486+
-> operations::mixed_primitive_dispatch_result_t<operations::Equal, Lhs,
487+
Rhs> {
488+
return operations::equal(lhs, rhs);
489+
}
490+
491+
template <operations::underlying_operand Lhs,
492+
operations::primitive_instance Rhs>
493+
constexpr auto operator==(Lhs const &lhs, Rhs const &rhs)
494+
-> operations::flipped_mixed_primitive_dispatch_result_t<operations::Equal,
495+
Lhs, Rhs> {
496+
return operations::equal(lhs, rhs);
497+
}
498+
256499
template <operations::primitive_instance Lhs,
257500
operations::primitive_instance Rhs>
258501
constexpr auto operator!=(Lhs const &lhs, Rhs const &rhs)
259502
-> operations::primitive_dispatch_result_t<operations::NotEqual, Lhs, Rhs> {
260503
return operations::not_equal(lhs, rhs);
261504
}
262505

506+
template <operations::primitive_instance Lhs,
507+
operations::underlying_operand Rhs>
508+
constexpr auto operator!=(Lhs const &lhs, Rhs const &rhs)
509+
-> operations::mixed_primitive_dispatch_result_t<operations::NotEqual, Lhs,
510+
Rhs> {
511+
return operations::not_equal(lhs, rhs);
512+
}
513+
514+
template <operations::underlying_operand Lhs,
515+
operations::primitive_instance Rhs>
516+
constexpr auto operator!=(Lhs const &lhs, Rhs const &rhs)
517+
-> operations::flipped_mixed_primitive_dispatch_result_t<
518+
operations::NotEqual, Lhs, Rhs> {
519+
return operations::not_equal(lhs, rhs);
520+
}
521+
263522
template <operations::primitive_instance Lhs,
264523
operations::primitive_instance Rhs>
265524
constexpr auto operator<=>(Lhs const &lhs, Rhs const &rhs)
266525
-> operations::three_way_dispatch_result_t<Lhs, Rhs> {
267526
return operations::three_way_compare(lhs, rhs);
268527
}
269528

529+
template <operations::primitive_instance Lhs,
530+
operations::underlying_operand Rhs>
531+
constexpr auto operator<=>(Lhs const &lhs, Rhs const &rhs)
532+
-> operations::mixed_three_way_dispatch_result_t<Lhs, Rhs> {
533+
return operations::three_way_compare(lhs, rhs);
534+
}
535+
536+
template <operations::underlying_operand Lhs,
537+
operations::primitive_instance Rhs>
538+
constexpr auto operator<=>(Lhs const &lhs, Rhs const &rhs)
539+
-> operations::flipped_mixed_three_way_dispatch_result_t<Lhs, Rhs> {
540+
return operations::three_way_compare(lhs, rhs);
541+
}
542+
270543
template <operations::primitive_instance Lhs,
271544
operations::primitive_instance Rhs>
272545
constexpr auto operator+=(Lhs &lhs, Rhs const &rhs)

0 commit comments

Comments
 (0)