@@ -644,6 +644,103 @@ TEST(OperationsTest, PrimitiveAliasMixesWithBuiltinArithmeticExplicitly) {
644644 EXPECT_EQ (result->value (), 43 );
645645}
646646
647+ TEST (OperationsTest, MixedBinaryOperationsSupportUnderlyingOnBothSides) {
648+ using value_t = primitive<int , policy::value::checked,
649+ policy::type::compatible, policy::error::expected>;
650+
651+ auto const lhs = value_t {40 };
652+ short const rhs = 2 ;
653+
654+ auto const apply_lr = operations::apply<operations::Addition>(lhs, rhs);
655+ auto const apply_rl = operations::apply<operations::Addition>(rhs, lhs);
656+ auto const add_lr = operations::add (lhs, rhs);
657+ auto const add_rl = operations::add (rhs, lhs);
658+ auto const sub_lr = operations::sub (lhs, rhs);
659+ auto const sub_rl = operations::sub (rhs, lhs);
660+ auto const div_lr = operations::div (lhs, rhs);
661+ auto const div_rl = operations::div (rhs, lhs);
662+ auto const cmp_lr = operations::three_way_compare (lhs, rhs);
663+ auto const cmp_rl = operations::three_way_compare (rhs, lhs);
664+
665+ static_assert (std::is_same_v<typename decltype (apply_lr)::value_type, value_t >);
666+ static_assert (std::is_same_v<typename decltype (apply_rl)::value_type, value_t >);
667+ static_assert (std::is_same_v<typename decltype (add_lr)::value_type, value_t >);
668+ static_assert (std::is_same_v<typename decltype (add_rl)::value_type, value_t >);
669+ static_assert (std::is_same_v<typename decltype (cmp_lr)::value_type,
670+ std::strong_ordering>);
671+ static_assert (std::is_same_v<typename decltype (cmp_rl)::value_type,
672+ std::strong_ordering>);
673+
674+ ASSERT_TRUE (apply_lr.has_value ());
675+ ASSERT_TRUE (apply_rl.has_value ());
676+ ASSERT_TRUE (add_lr.has_value ());
677+ ASSERT_TRUE (add_rl.has_value ());
678+ ASSERT_TRUE (sub_lr.has_value ());
679+ ASSERT_TRUE (sub_rl.has_value ());
680+ ASSERT_TRUE (div_lr.has_value ());
681+ ASSERT_TRUE (div_rl.has_value ());
682+ ASSERT_TRUE (cmp_lr.has_value ());
683+ ASSERT_TRUE (cmp_rl.has_value ());
684+
685+ EXPECT_EQ (apply_lr->value (), 42 );
686+ EXPECT_EQ (apply_rl->value (), 42 );
687+ EXPECT_EQ (add_lr->value (), 42 );
688+ EXPECT_EQ (add_rl->value (), 42 );
689+ EXPECT_EQ (sub_lr->value (), 38 );
690+ EXPECT_EQ (sub_rl->value (), -38 );
691+ EXPECT_EQ (div_lr->value (), 20 );
692+ EXPECT_EQ (div_rl->value (), 0 );
693+ EXPECT_EQ (*cmp_lr, std::strong_ordering::greater);
694+ EXPECT_EQ (*cmp_rl, std::strong_ordering::less);
695+ }
696+
697+ TEST (OperationsTest, MixedFrameworkOperatorsSupportUnderlyingOnBothSides) {
698+ using namespace mcpplibs ::primitives::operators;
699+ using value_t = primitive<int , policy::value::checked,
700+ policy::type::compatible, policy::error::expected>;
701+
702+ auto const lhs = value_t {40 };
703+ short const rhs = 2 ;
704+
705+ auto const add_lr = lhs + rhs;
706+ auto const add_rl = rhs + lhs;
707+ auto const sub_lr = lhs - rhs;
708+ auto const sub_rl = rhs - lhs;
709+ auto const eq_lr = lhs == static_cast <short >(40 );
710+ auto const eq_rl = static_cast <short >(40 ) == lhs;
711+ auto const ne_lr = lhs != static_cast <short >(41 );
712+ auto const ne_rl = static_cast <short >(41 ) != lhs;
713+ auto const cmp_lr = lhs <=> rhs;
714+ auto const cmp_rl = rhs <=> lhs;
715+
716+ static_assert (std::is_same_v<typename decltype (cmp_lr)::value_type,
717+ std::strong_ordering>);
718+ static_assert (std::is_same_v<typename decltype (cmp_rl)::value_type,
719+ std::strong_ordering>);
720+
721+ ASSERT_TRUE (add_lr.has_value ());
722+ ASSERT_TRUE (add_rl.has_value ());
723+ ASSERT_TRUE (sub_lr.has_value ());
724+ ASSERT_TRUE (sub_rl.has_value ());
725+ ASSERT_TRUE (eq_lr.has_value ());
726+ ASSERT_TRUE (eq_rl.has_value ());
727+ ASSERT_TRUE (ne_lr.has_value ());
728+ ASSERT_TRUE (ne_rl.has_value ());
729+ ASSERT_TRUE (cmp_lr.has_value ());
730+ ASSERT_TRUE (cmp_rl.has_value ());
731+
732+ EXPECT_EQ (add_lr->value (), 42 );
733+ EXPECT_EQ (add_rl->value (), 42 );
734+ EXPECT_EQ (sub_lr->value (), 38 );
735+ EXPECT_EQ (sub_rl->value (), -38 );
736+ EXPECT_EQ (eq_lr->value (), 1 );
737+ EXPECT_EQ (eq_rl->value (), 1 );
738+ EXPECT_EQ (ne_lr->value (), 1 );
739+ EXPECT_EQ (ne_rl->value (), 1 );
740+ EXPECT_EQ (*cmp_lr, std::strong_ordering::greater);
741+ EXPECT_EQ (*cmp_rl, std::strong_ordering::less);
742+ }
743+
647744TEST (OperationsTest, OperatorEqualDelegatesToDispatcher) {
648745 using namespace mcpplibs ::primitives::operators;
649746 using value_t = primitive<int , policy::value::checked, policy::type::strict,
0 commit comments