Skip to content

Commit 60cf921

Browse files
refactor: Update import statements and add new tests for underlying operations
1 parent 77d704a commit 60cf921

3 files changed

Lines changed: 157 additions & 45 deletions

File tree

tests/basic/test_policies.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
#include <atomic>
22
#include <gtest/gtest.h>
33
#include <type_traits>
4+
45
import mcpplibs.primitives.policy;
5-
import mcpplibs.primitives.operations;
6+
import mcpplibs.primitives.underlying;
7+
import mcpplibs.primitives.operations.traits;
8+
import mcpplibs.primitives.operations.impl;
69

710
using namespace mcpplibs::primitives;
811

tests/basic/test_underlying.cpp

Lines changed: 1 addition & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import mcpplibs.primitives.underlying;
44
import mcpplibs.primitives.primitive;
55
import mcpplibs.primitives.policy;
6-
import mcpplibs.primitives.operations;
6+
import mcpplibs.primitives.operations.impl;
77

88
namespace {
99

@@ -579,49 +579,6 @@ TEST(PrimitiveTraitsTest, CustomNumericLikeRepTypeRejectsInvalidCategory) {
579579
EXPECT_FALSE((mcpplibs::primitives::underlying_type<BadCustomKind>));
580580
}
581581

582-
TEST(PrimitiveTraitsTest, CustomUnderlyingParticipatesInPrimitiveOperations) {
583-
using value_t = mcpplibs::primitives::primitive<
584-
BigIntLike, mcpplibs::primitives::policy::value::checked,
585-
mcpplibs::primitives::policy::error::expected>;
586-
587-
auto const lhs = value_t{BigIntLike{40}};
588-
auto const rhs = value_t{BigIntLike{2}};
589-
590-
auto const result = mcpplibs::primitives::operations::add(lhs, rhs);
591-
592-
ASSERT_TRUE(result.has_value());
593-
EXPECT_EQ(result->value().value, 42);
594-
}
595-
596-
TEST(PrimitiveTraitsTest, CustomWrappedUnderlyingUsesRepBridgeForArithmetic) {
597-
using value_t = mcpplibs::primitives::primitive<
598-
UserInteger, mcpplibs::primitives::policy::value::checked,
599-
mcpplibs::primitives::policy::error::expected>;
600-
601-
auto const lhs = value_t{UserInteger{40}};
602-
auto const rhs = value_t{UserInteger{2}};
603-
604-
auto const result = mcpplibs::primitives::operations::add(lhs, rhs);
605-
606-
ASSERT_TRUE(result.has_value());
607-
EXPECT_EQ(result->value(), 42);
608-
}
609-
610-
TEST(PrimitiveTraitsTest, InvalidUnderlyingRepIsRejectedByDispatcher) {
611-
using value_t = mcpplibs::primitives::primitive<
612-
NonNegativeInt, mcpplibs::primitives::policy::value::checked,
613-
mcpplibs::primitives::policy::error::expected>;
614-
615-
auto const lhs = value_t{NonNegativeInt{-1}};
616-
auto const rhs = value_t{NonNegativeInt{2}};
617-
618-
auto const result = mcpplibs::primitives::operations::add(lhs, rhs);
619-
620-
ASSERT_FALSE(result.has_value());
621-
EXPECT_EQ(result.error(),
622-
mcpplibs::primitives::policy::error::kind::domain_error);
623-
}
624-
625582
TEST(PrimitiveTraitsTest,
626583
CustomNumericLikeRepTypeRequiresDivisionOperatorForEligibility) {
627584
EXPECT_TRUE(
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
#include <gtest/gtest.h>
2+
3+
import mcpplibs.primitives.underlying;
4+
import mcpplibs.primitives.primitive;
5+
import mcpplibs.primitives.policy;
6+
import mcpplibs.primitives.operations.impl;
7+
import mcpplibs.primitives.operations.dispatcher;
8+
9+
using namespace mcpplibs::primitives;
10+
11+
namespace {
12+
13+
struct OpsBigIntLike {
14+
long long value;
15+
16+
friend constexpr auto operator+(OpsBigIntLike lhs,
17+
OpsBigIntLike rhs) noexcept
18+
-> OpsBigIntLike {
19+
return OpsBigIntLike{lhs.value + rhs.value};
20+
}
21+
22+
friend constexpr auto operator-(OpsBigIntLike lhs,
23+
OpsBigIntLike rhs) noexcept
24+
-> OpsBigIntLike {
25+
return OpsBigIntLike{lhs.value - rhs.value};
26+
}
27+
28+
friend constexpr auto operator*(OpsBigIntLike lhs,
29+
OpsBigIntLike rhs) noexcept
30+
-> OpsBigIntLike {
31+
return OpsBigIntLike{lhs.value * rhs.value};
32+
}
33+
34+
friend constexpr auto operator/(OpsBigIntLike lhs,
35+
OpsBigIntLike rhs) noexcept
36+
-> OpsBigIntLike {
37+
return OpsBigIntLike{lhs.value / rhs.value};
38+
}
39+
40+
friend constexpr auto operator==(OpsBigIntLike lhs,
41+
OpsBigIntLike rhs) noexcept -> bool {
42+
return lhs.value == rhs.value;
43+
}
44+
};
45+
46+
struct OpsUserInteger {
47+
int value;
48+
};
49+
50+
struct OpsNonNegativeInt {
51+
int value;
52+
};
53+
54+
} // namespace
55+
56+
template <>
57+
struct mcpplibs::primitives::underlying::traits<OpsBigIntLike> {
58+
using value_type = OpsBigIntLike;
59+
using rep_type = OpsBigIntLike;
60+
61+
static constexpr bool enabled = true;
62+
static constexpr auto kind = category::integer;
63+
64+
static constexpr auto to_rep(value_type value) noexcept -> rep_type {
65+
return value;
66+
}
67+
68+
static constexpr auto from_rep(rep_type value) noexcept -> value_type {
69+
return value;
70+
}
71+
72+
static constexpr auto is_valid_rep(rep_type) noexcept -> bool { return true; }
73+
};
74+
75+
template <>
76+
struct mcpplibs::primitives::underlying::traits<OpsUserInteger> {
77+
using value_type = OpsUserInteger;
78+
using rep_type = int;
79+
80+
static constexpr bool enabled = true;
81+
static constexpr auto kind = category::integer;
82+
83+
static constexpr auto to_rep(value_type value) noexcept -> rep_type {
84+
return value.value;
85+
}
86+
87+
static constexpr auto from_rep(rep_type value) noexcept -> value_type {
88+
return OpsUserInteger{value};
89+
}
90+
91+
static constexpr auto is_valid_rep(rep_type) noexcept -> bool { return true; }
92+
};
93+
94+
template <>
95+
struct mcpplibs::primitives::underlying::traits<OpsNonNegativeInt> {
96+
using value_type = OpsNonNegativeInt;
97+
using rep_type = int;
98+
99+
static constexpr bool enabled = true;
100+
static constexpr auto kind = category::integer;
101+
102+
static constexpr auto to_rep(value_type value) noexcept -> rep_type {
103+
return value.value;
104+
}
105+
106+
static constexpr auto from_rep(rep_type value) noexcept -> value_type {
107+
return OpsNonNegativeInt{value};
108+
}
109+
110+
static constexpr auto is_valid_rep(rep_type value) noexcept -> bool {
111+
return value >= 0;
112+
}
113+
};
114+
115+
TEST(UnderlyingOperationsTest, CustomUnderlyingParticipatesInPrimitiveOperations) {
116+
using value_t =
117+
primitive<OpsBigIntLike, policy::value::checked, policy::error::expected>;
118+
119+
auto const lhs = value_t{OpsBigIntLike{40}};
120+
auto const rhs = value_t{OpsBigIntLike{2}};
121+
122+
auto const result = operations::dispatch<operations::Addition>(lhs, rhs);
123+
124+
ASSERT_TRUE(result.has_value());
125+
EXPECT_EQ(result->value, 42);
126+
}
127+
128+
TEST(UnderlyingOperationsTest, CustomWrappedUnderlyingUsesRepBridgeForArithmetic) {
129+
using value_t =
130+
primitive<OpsUserInteger, policy::value::checked, policy::error::expected>;
131+
132+
auto const lhs = value_t{OpsUserInteger{40}};
133+
auto const rhs = value_t{OpsUserInteger{2}};
134+
135+
auto const result = operations::dispatch<operations::Addition>(lhs, rhs);
136+
137+
ASSERT_TRUE(result.has_value());
138+
EXPECT_EQ(*result, 42);
139+
}
140+
141+
TEST(UnderlyingOperationsTest, InvalidUnderlyingRepIsRejectedByDispatcher) {
142+
using value_t = primitive<OpsNonNegativeInt, policy::value::checked,
143+
policy::error::expected>;
144+
145+
auto const lhs = value_t{OpsNonNegativeInt{-1}};
146+
auto const rhs = value_t{OpsNonNegativeInt{2}};
147+
148+
auto const result = operations::dispatch<operations::Addition>(lhs, rhs);
149+
150+
ASSERT_FALSE(result.has_value());
151+
EXPECT_EQ(result.error(), policy::error::kind::domain_error);
152+
}

0 commit comments

Comments
 (0)