@@ -232,46 +232,17 @@ class annotated_arg {
232
232
template<typename propertyT>
233
233
static constexpr /*unspecified*/ get_property();
234
234
235
- // Overloaded arithmetic operators
236
- template <typename T2, typename PropertyList2,
237
- typename R = decltype(std::declval<T>() + std::declval<T2>())>
238
- R operator+(const annotated_arg<T2, PropertyList2> &other) const;
239
-
240
- template <typename T2, typename PropertyList2,
241
- typename R = decltype(std::declval<T>() - std::declval<T2>())>
242
- R operator-(const annotated_arg<T2, PropertyList2> &other) const;
243
-
244
- template <typename T2, typename PropertyList2,
245
- typename R = decltype(std::declval<T>() * std::declval<T2>())>
246
- R operator*(const annotated_arg<T2, PropertyList2> &other) const;
247
-
248
- template <typename T2, typename PropertyList2,
249
- typename R = decltype(std::declval<T>() / std::declval<T2>())>
250
- R operator/(const annotated_arg<T2, PropertyList2> &other) const;
251
-
252
- template <typename T2, typename PropertyList2,
253
- typename R = decltype(std::declval<T>() % std::declval<T2>())>
254
- R operator%(const annotated_arg<T2, PropertyList2> &other) const;
255
-
256
- template <typename T2, typename PropertyList2,
257
- typename R = decltype(std::declval<T>() & std::declval<T2>())>
258
- R operator&(const annotated_arg<T2, PropertyList2> &other) const;
259
-
260
- template <typename T2, typename PropertyList2,
261
- typename R = decltype(std::declval<T>() | std::declval<T2>())>
262
- R operator|(const annotated_arg<T2, PropertyList2> &other) const;
263
-
264
- template <typename T2, typename PropertyList2,
265
- typename R = decltype(std::declval<T>() ^ std::declval<T2>())>
266
- R operator^(const annotated_arg<T2, PropertyList2> &other) const;
267
-
268
- template <typename T2, typename PropertyList2,
269
- typename R = decltype(std::declval<T>() >> std::declval<T2>())>
270
- R operator>>(const annotated_arg<T2, PropertyList2> &other) const;
271
-
272
- template <typename T2, typename PropertyList2,
273
- typename R = decltype(std::declval<T>() << std::declval<T2>())>
274
- R operator<<(const annotated_arg<T2, PropertyList2> &other) const;
235
+ // OP is: +, -, *, /, %, <<, >>, &, |, ^, <, <=, >, >=, ==, ~=, &&, ||
236
+ template <typename O>
237
+ auto friend operatorOP(O&& a, const annotated_arg& b) ->
238
+ decltype(std::forward<O>(a) OP std::declval<T>());
239
+ template <typename O> //available only if O is not an annotated_arg type
240
+ auto friend operatorOP(const annotated_arg& a, O&& b) ->
241
+ decltype(std::declval<T>() OP std::forward<O>(b));
242
+
243
+ // OP is: +, -, !, ~
244
+ template <typename O=T>
245
+ auto operatorOP() -> decltype(OP std::declval<O>());
275
246
};
276
247
277
248
//Deduction guides
@@ -283,86 +254,6 @@ template <typename T, typename PropertiesA, typename PropertiesB>
283
254
annotated_arg(annotated_arg<T, PropertiesA>, PropertiesB>) ->
284
255
annotated_arg<T, /* a type that combines the properties of PropertiesA and PropertiesB */>;
285
256
286
- // Overloaded operators for raw type
287
- template <typename T, typename PropertyList, typename T2,
288
- typename R = decltype(std::declval<T>() + std::declval<T2>())>
289
- R operator+(const annotated_arg<T, PropertyList> &a, const T2 &b);
290
-
291
- template <typename T, typename PropertyList, typename T2,
292
- typename R = decltype(std::declval<T>() - std::declval<T2>())>
293
- R operator-(const annotated_arg<T, PropertyList> &a, const T2 &b);
294
-
295
- template <typename T, typename PropertyList, typename T2,
296
- typename R = decltype(std::declval<T>() * std::declval<T2>())>
297
- R operator*(const annotated_arg<T, PropertyList> &a, const T2 &b);
298
-
299
- template <typename T, typename PropertyList, typename T2,
300
- typename R = decltype(std::declval<T>() / std::declval<T2>())>
301
- R operator/(const annotated_arg<T, PropertyList> &a, const T2 &b);
302
-
303
- template <typename T, typename PropertyList, typename T2,
304
- typename R = decltype(std::declval<T>() % std::declval<T2>())>
305
- R operator%(const annotated_arg<T, PropertyList> &a, const T2 &b);
306
-
307
- template <typename T, typename PropertyList, typename T2,
308
- typename R = decltype(std::declval<T>() & std::declval<T2>())>
309
- R operator&(const annotated_arg<T, PropertyList> &a, const T2 &b);
310
-
311
- template <typename T, typename PropertyList, typename T2,
312
- typename R = decltype(std::declval<T>() | std::declval<T2>())>
313
- R operator|(const annotated_arg<T, PropertyList> &a, const T2 &b);
314
-
315
- template <typename T, typename PropertyList, typename T2,
316
- typename R = decltype(std::declval<T>() ^ std::declval<T2>())>
317
- R operator^(const annotated_arg<T, PropertyList> &a, const T2 &b);
318
-
319
- template <typename T, typename PropertyList, typename T2,
320
- typename R = decltype(std::declval<T>() >> std::declval<T2>())>
321
- R operator>>(const annotated_arg<T, PropertyList> &a, const T2 &b);
322
-
323
- template <typename T, typename PropertyList, typename T2,
324
- typename R = decltype(std::declval<T>() << std::declval<T2>())>
325
- R operator<<(const annotated_arg<T, PropertyList> &a, const T2 &b);
326
-
327
- template <typename T, typename T2, typename PropertyList2,
328
- typename R = decltype(std::declval<T>() + std::declval<T2>())>
329
- R operator+(const T &a, const annotated_arg<T2, PropertyList2> &b);
330
-
331
- template <typename T, typename T2, typename PropertyList2,
332
- typename R = decltype(std::declval<T>() - std::declval<T2>())>
333
- R operator-(const T &a, const annotated_arg<T2, PropertyList2> &b);
334
-
335
- template <typename T, typename T2, typename PropertyList2,
336
- typename R = decltype(std::declval<T>() * std::declval<T2>())>
337
- R operator*(const T &a, const annotated_arg<T2, PropertyList2> &b);
338
-
339
- template <typename T, typename T2, typename PropertyList2,
340
- typename R = decltype(std::declval<T>() / std::declval<T2>())>
341
- R operator/(const T &a, const annotated_arg<T2, PropertyList2> &b);
342
-
343
- template <typename T, typename T2, typename PropertyList2,
344
- typename R = decltype(std::declval<T>() % std::declval<T2>())>
345
- R operator%(const T &a, const annotated_arg<T2, PropertyList2> &b);
346
-
347
- template <typename T, typename T2, typename PropertyList2,
348
- typename R = decltype(std::declval<T>() & std::declval<T2>())>
349
- R operator&(const T &a, const annotated_arg<T2, PropertyList2> &b);
350
-
351
- template <typename T, typename T2, typename PropertyList2,
352
- typename R = decltype(std::declval<T>() | std::declval<T2>())>
353
- R operator|(const T &a, const annotated_arg<T2, PropertyList2> &b);
354
-
355
- template <typename T, typename T2, typename PropertyList2,
356
- typename R = decltype(std::declval<T>() ^ std::declval<T2>())>
357
- R operator^(const T &a, const annotated_arg<T2, PropertyList2> &b);
358
-
359
- template <typename T, typename T2, typename PropertyList2,
360
- typename R = decltype(std::declval<T>() >> std::declval<T2>())>
361
- R operator>>(const T &a, const annotated_arg<T2, PropertyList2> &b);
362
-
363
- template <typename T, typename T2, typename PropertyList2,
364
- typename R = decltype(std::declval<T>() << std::declval<T2>())>
365
- R operator<<(const T &a, const annotated_arg<T2, PropertyList2> &b);
366
257
367
258
} // namespace sycl::ext::oneapi::experimental
368
259
----
@@ -512,41 +403,55 @@ constant property.
512
403
a|
513
404
[source,c++]
514
405
----
515
- template <typename T2, typename PropertyList2,
516
- typename R = decltype(std::declval<T>() OP std::declval<T2>()) >
517
- R operatorOP(const annotated_arg<T2, PropertyList2> &other) const ;
406
+ template <typename O>
407
+ auto friend operatorOP(O&& a, const annotated_arg& b) - >
408
+ decltype(std::forward<O>(a) OP std::declval<T>()) ;
518
409
----
519
- |
520
- Defines the overloaded operators for types `annotated_arg<T, ...>` and
521
- `annotated_arg<T2, ...>`. Let `operatorOP` denote the operator used.
522
- The overloaded operator `operatorOP` utilizes `operatorOP(T, T2)` and
523
- is available only if `operatorOP(T, T2)` is well formed. The value and result
524
- is the same as the result of `operatorOP(T, T2)` applied to the objects of
525
- type `T` and `T2`.
410
+ a|
411
+ Where [code]#OP# is: [code]#pass:[+]#, [code]#-#,[code]#*#, [code]#/#, [code]#%#, [code]#+<<+#, [code]#>>#, [code]#&#, [code]#\|#, [code]#\^#, [code]#<#, [code]#<=#, [code]#>#, [code]#>=#, [code]#==#, [code]#!=#, [code]#&&#, [code]#\|\|#.
526
412
527
- `operatorOP` is any of the following: `operator+`, `operator-`, `operator*`, `operator/`,
528
- `operator%`, `operator&`, `operator\|`, `operator^`, `operator>>`, and `operator<<`.
413
+ Defines a hidden friend operator `OP` overload for type `O` and `annotated_arg`.
529
414
530
- |===
415
+ Let `operatorOP` denotes the operator used. The overloaded operator `operatorOP` utilizes
416
+ `operatorOP(O&&, T&&)` and is available only if `operatorOP(O&&, T&&)` is well formed. The value and result
417
+ is the same as the result of `operatorOP(O&&, T&&)` applied to the objects of
418
+ type `O` and `T`.
531
419
532
- Free functions of the following form are defined for the overloaded operators for types
533
- `annotated_arg<T, ...>` and raw type `T2`. Let `operatorOP` denote the operator used.
534
- The overloaded operator `operatorOP` utilizes `operatorOP(T, T2)` and is available only
535
- if `operatorOP(T, T2)` is well formed. The value and result is the same as the result of
536
- `operatorOP(T, T2)` applied to the underlying objects of type `T` and `T2`.
420
+ a|
421
+ [source,c++]
422
+ ----
423
+ template <typename O>
424
+ auto friend operatorOP(const annotated_ref& a, O&& b) ->
425
+ decltype(std::declval<T>() OP std::forward<O>(b));
426
+ ----
427
+ a|
428
+ Where [code]#OP# is: [code]#pass:[+]#, [code]#-#,[code]#*#, [code]#/#, [code]#%#, [code]#+<<+#, [code]#>>#, [code]#&#, [code]#\|#, [code]#\^#, [code]#<#, [code]#<=#, [code]#>#, [code]#>=#, [code]#==#, [code]#!=#, [code]#&&#, [code]#\|\|#.
429
+
430
+ Defines a hidden friend operator `OP` overload for type `annotated_arg` and `O`. `O` cannot be
431
+ a type of `annotated_arg`.
537
432
433
+ Let `operatorOP` denotes the operator used. The overloaded operator `operatorOP` utilizes
434
+ `operatorOP(T&&, O&&)` and is available only if `operatorOP(T&&, O&&)` is well formed. The value and result
435
+ is the same as the result of `operatorOP(T&&, O&&)` applied to the objects of
436
+ type `T` and `O`.
437
+
438
+ a|
538
439
[source,c++]
539
440
----
540
- template <typename T, typename PropertyList, typename T2,
541
- typename R = decltype(std::declval<T>() OP std::declval<T2>())>
542
- R operatorOP(const annotated_arg<T, PropertyList> &a, const T2 &b);
543
- template <typename T, typename T2, typename PropertyList2,
544
- typename R = decltype(std::declval<T>() OP std::declval<T2>())>
545
- R operatorOP(const T &a, const annotated_arg<T2, PropertyList2> &b);
441
+ template <typename O=T>
442
+ auto operatorOP() -> decltype(OP std::declval<O>());
546
443
----
444
+ a|
445
+ Where [code]#OP# is: [code]#pass:[+]#, [code]#-#, [code]#!#, [code]#~#.
446
+
447
+ Defines a operator `OP` overload for types `O` where the default type is `T`.
547
448
548
- `operatorOP` is any of the following: `operator+`, `operator-`, `operator*`, `operator/`,
549
- `operator%`, `operator&`, `operator\|`, `operator^`, `operator>>`, and `operator<<`.
449
+ Let `operatorOP` denotes the operator used. The overloaded operator
450
+ `operatorOP` utilizes `operatorOP(O)` and is available only if `operatorOP(O)`
451
+ is well formed. The value and result is the same as the result of `operatorOP(O)`
452
+ applied to the objects of type `O`.
453
+
454
+ |===
550
455
551
456
== Issues
552
457
0 commit comments