@@ -384,6 +384,45 @@ TEST(OperationsTest, TransparentTypePrimitiveConstructorAllowsCrossCategory) {
384384 EXPECT_EQ (value.load (), 42 );
385385}
386386
387+ TEST (OperationsTest, PrimitiveSpecialMembersSupportCrossUnderlyingWithCompatibleType) {
388+ using dst_t =
389+ primitive<int , policy::type::compatible, policy::error::expected>;
390+ using src_t =
391+ primitive<short , policy::type::compatible, policy::error::expected>;
392+
393+ static_assert (std::is_constructible_v<dst_t , src_t const &>);
394+ static_assert (std::is_constructible_v<dst_t , src_t &&>);
395+ static_assert (std::is_assignable_v<dst_t &, src_t const &>);
396+ static_assert (std::is_assignable_v<dst_t &, src_t &&>);
397+
398+ auto const source = src_t {40 };
399+ auto copy_constructed = dst_t {source};
400+ EXPECT_EQ (copy_constructed.load (), 40 );
401+
402+ auto move_constructed = dst_t {src_t {41 }};
403+ EXPECT_EQ (move_constructed.load (), 41 );
404+
405+ auto copy_assigned = dst_t {0 };
406+ copy_assigned = source;
407+ EXPECT_EQ (copy_assigned.load (), 40 );
408+
409+ auto move_assigned = dst_t {0 };
410+ auto move_source = src_t {42 };
411+ move_assigned = std::move (move_source);
412+ EXPECT_EQ (move_assigned.load (), 42 );
413+ }
414+
415+ TEST (OperationsTest,
416+ PrimitiveSpecialMembersRejectCrossUnderlyingWithStrictType) {
417+ using dst_t = primitive<int , policy::type::strict, policy::error::expected>;
418+ using src_t = primitive<short , policy::type::strict, policy::error::expected>;
419+
420+ static_assert (!std::is_constructible_v<dst_t , src_t const &>);
421+ static_assert (!std::is_constructible_v<dst_t , src_t &&>);
422+ static_assert (!std::is_assignable_v<dst_t &, src_t const &>);
423+ static_assert (!std::is_assignable_v<dst_t &, src_t &&>);
424+ }
425+
387426TEST (OperationsTest, DispatcherMetaTracksResolvedPolicyGroupConsistency) {
388427 using aligned_lhs_t = primitive<int , policy::value::checked,
389428 policy::error::expected>;
0 commit comments