@@ -397,11 +397,40 @@ template <stdx::ct_string Name, typename... Fields> struct message {
397
397
[[nodiscard]] constexpr auto data () const { return storage; }
398
398
399
399
[[nodiscard]] constexpr auto as_owning () { return owner_t {*this }; }
400
+ [[nodiscard]] constexpr auto as_const_view () const {
401
+ using cv_t =
402
+ view_t <stdx::span<std::add_const_t <typename Span::value_type>,
403
+ stdx::ct_capacity_v<Span>>>;
404
+ return cv_t {*this };
405
+ }
400
406
401
407
private:
402
408
static_assert (definition_t ::fits_inside<span_t >,
403
409
" Fields overflow message storage!" );
404
410
span_t storage{};
411
+
412
+ friend constexpr auto operator ==(view_t , view_t ) -> bool {
413
+ static_assert (stdx::always_false_v<Span>,
414
+ " Equality is not defined for messages: "
415
+ " consider using equivalent() instead." );
416
+ return false ;
417
+ }
418
+
419
+ using const_span_t =
420
+ stdx::span<std::add_const_t <typename Span::value_type>,
421
+ stdx::ct_capacity_v<Span>>;
422
+ using mutable_span_t =
423
+ stdx::span<typename Span::value_type, stdx::ct_capacity_v<Span>>;
424
+
425
+ friend constexpr auto equiv (view_t lhs,
426
+ view_t <const_span_t > rhs) -> bool {
427
+ return (... and (lhs.get (Fields{}) == rhs.get (Fields{})));
428
+ }
429
+
430
+ friend constexpr auto equiv (view_t lhs,
431
+ view_t <mutable_span_t > rhs) -> bool {
432
+ return equiv (lhs, rhs.as_const_view ());
433
+ }
405
434
};
406
435
using const_view_t = view_t <default_const_span_t >;
407
436
using mutable_view_t = view_t <default_span_t >;
@@ -478,9 +507,27 @@ template <stdx::ct_string Name, typename... Fields> struct message {
478
507
" Fields overflow message storage!" );
479
508
storage_t storage{};
480
509
481
- friend constexpr auto operator ==(owner_t const &lhs,
482
- owner_t const &rhs) -> bool {
483
- return lhs.storage == rhs.storage ;
510
+ friend constexpr auto operator ==(owner_t const &,
511
+ owner_t const &) -> bool {
512
+ static_assert (stdx::always_false_v<Storage>,
513
+ " Equality is not defined for messages: "
514
+ " consider using equivalent() instead." );
515
+ return false ;
516
+ }
517
+
518
+ using const_span_t = stdx::span<typename Storage::value_type const ,
519
+ stdx::ct_capacity_v<Storage>>;
520
+ using mutable_span_t = stdx::span<typename Storage::value_type,
521
+ stdx::ct_capacity_v<Storage>>;
522
+
523
+ friend constexpr auto equiv (owner_t const &lhs,
524
+ view_t <const_span_t > rhs) -> bool {
525
+ return (... and (lhs.get (Fields{}) == rhs.get (Fields{})));
526
+ }
527
+
528
+ friend constexpr auto equiv (owner_t const &lhs,
529
+ view_t <mutable_span_t > rhs) -> bool {
530
+ return equiv (lhs, rhs.as_const_view ());
484
531
}
485
532
};
486
533
@@ -518,8 +565,8 @@ template <stdx::ct_string Name, typename... Fields> struct message {
518
565
519
566
using matcher_t = decltype (match::all(typename Fields::matcher_t {}...));
520
567
521
- // NewFields go first because they override existing fields of the same name
522
- // (see unique_by_name)
568
+ // NewFields go first because they override existing fields of the same
569
+ // name (see unique_by_name)
523
570
template <stdx::ct_string NewName, typename ... NewFields>
524
571
using extension =
525
572
message_without_unique_field_names<NewName, NewFields..., Fields...>;
@@ -534,6 +581,16 @@ template <typename T> using owning = typename T::template owner_t<>;
534
581
template <typename T> using mutable_view = typename T::mutable_view_t ;
535
582
template <typename T> using const_view = typename T::const_view_t ;
536
583
584
+ template <typename M>
585
+ concept messagelike =
586
+ requires { typename std::remove_cvref_t <M>::definition_t ; };
587
+ template <typename M>
588
+ concept viewlike =
589
+ messagelike<M> and requires { typename std::remove_cvref_t <M>::span_t ; };
590
+ template <typename M>
591
+ concept owninglike =
592
+ messagelike<M> and requires { typename std::remove_cvref_t <M>::storage_t ; };
593
+
537
594
template <typename V, typename Def>
538
595
concept view_of = std::same_as<typename V::definition_t , Def> and
539
596
Def::template fits_inside<typename V::span_t >;
@@ -543,4 +600,26 @@ concept const_view_of =
543
600
544
601
template <typename Def, stdx::ct_string Name, typename ... Fields>
545
602
using extend = typename Def::template extension<Name, Fields...>;
603
+
604
+ template <owninglike O,
605
+ view_of<typename std::remove_cvref_t <O>::definition_t > V>
606
+ constexpr auto equivalent (O &&o, V v) -> bool {
607
+ return equiv (std::forward<O>(o), v);
608
+ }
609
+
610
+ template <owninglike O,
611
+ view_of<typename std::remove_cvref_t <O>::definition_t > V>
612
+ constexpr auto equivalent (V v, O &&o) -> bool {
613
+ return equiv (std::forward<O>(o), v);
614
+ }
615
+
616
+ template <viewlike V1, view_of<typename V1::definition_t > V2>
617
+ constexpr auto equivalent (V1 v1, V2 v2) -> bool {
618
+ return equiv (v1, v2);
619
+ }
620
+
621
+ template <owninglike O1, owninglike O2>
622
+ constexpr auto equivalent (O1 const &lhs, O2 const &rhs) {
623
+ return equiv (lhs, rhs.as_const_view ());
624
+ }
546
625
} // namespace msg
0 commit comments