Skip to content

Commit 0a4ff64

Browse files
committed
Allow implicit promotion from unsigned values to usize
1 parent 1bf01f6 commit 0a4ff64

File tree

8 files changed

+213
-218
lines changed

8 files changed

+213
-218
lines changed

containers/array.h

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,12 @@
2222

2323
#include "assertions/check.h"
2424
#include "construct/make_default.h"
25+
#include "fn/callable.h"
2526
#include "marker/unsafe.h"
2627
#include "mem/move.h"
2728
#include "mem/relocate.h"
2829
#include "num/num_concepts.h"
30+
#include "num/unsigned_integer.h"
2931

3032
namespace sus::containers {
3133

@@ -69,14 +71,15 @@ class Array final {
6971
return Array(kWithUninitialized);
7072
}
7173

72-
template <class InitializerFn>
74+
template <::sus::fn::callable::CallableReturns<T> InitializerFn>
7375
constexpr static Array with_initializer(InitializerFn f) noexcept {
7476
return Array(kWithInitializer, move(f), std::make_index_sequence<N>());
7577
}
7678

77-
constexpr static Array with_value(const T& t) noexcept
78-
requires(std::is_copy_constructible_v<T>)
79-
{
79+
// Uses convertible_to<T> to accept `sus::into()` values. But doesn't use
80+
// sus::construct::Into<T> to avoid implicit conversions.
81+
template <std::convertible_to<T> U>
82+
constexpr static Array with_value(const U& t) noexcept {
8083
return Array(kWithValue, t, std::make_index_sequence<N>());
8184
}
8285

@@ -92,21 +95,21 @@ class Array final {
9295
}
9396

9497
/// Returns the number of elements in the array.
95-
constexpr const /* TODO: usize */ size_t len() const& noexcept { return N; }
98+
constexpr const usize len() const& noexcept { return N; }
9699

97-
constexpr const T& get(/* TODO: usize */ size_t i) const& noexcept
100+
constexpr const T& get(usize i) const& noexcept
98101
requires(N > 0)
99102
{
100-
check(i < N);
101-
return storage_.data_[i];
103+
check(i.primitive_value < N);
104+
return storage_.data_[i.primitive_value];
102105
}
103-
constexpr const T& get(/* TODO: usize */ size_t i) && = delete;
106+
constexpr const T& get(usize i) && = delete;
104107

105-
constexpr T& get_mut(/* TODO: usize */ size_t i) & noexcept
108+
constexpr T& get_mut(usize i) & noexcept
106109
requires(N > 0)
107110
{
108-
check(i < N);
109-
return storage_.data_[i];
111+
check(i.primitive_value < N);
112+
return storage_.data_[i.primitive_value];
110113
}
111114

112115
const T* as_ptr() const& noexcept

containers/array_unittest.cc

Lines changed: 46 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ struct NonAggregate {
6767
TEST(Array, WithDefault) {
6868
auto a = Array<int, 5>::with_default();
6969
static_assert(sizeof(a) == sizeof(int[5]));
70-
for (size_t i = 0; i < 5; ++i) {
70+
for (auto i = 0_usize; i < 5_usize; i += 1_usize) {
7171
EXPECT_EQ(a.get(i), 0);
7272
}
7373

@@ -87,62 +87,62 @@ TEST(Array, WithUninitialized) {
8787
}
8888

8989
TEST(Array, WithInitializer) {
90-
auto a = Array<int, 5>::with_initializer([i = 1]() mutable { return i++; });
91-
static_assert(sizeof(a) == sizeof(int[5]));
92-
for (size_t i = 0; i < 5; ++i) {
93-
EXPECT_EQ(a.get(i), i + 1);
90+
auto a =
91+
Array<usize, 5>::with_initializer([i = 1u]() mutable { return i++; });
92+
static_assert(sizeof(a) == sizeof(usize[5]));
93+
for (auto i = 0_usize; i < 5_usize; i += 1_usize) {
94+
EXPECT_EQ(a.get(i), i + 1_usize);
9495
}
9596

9697
struct NotTriviallyDefaultConstructible {
9798
NotTriviallyDefaultConstructible() {}
98-
NotTriviallyDefaultConstructible(int i) : i(i) {}
99-
int i;
99+
NotTriviallyDefaultConstructible(usize i) : i(i) {}
100+
usize i;
100101
};
101102
static_assert(!std::is_trivially_default_constructible_v<
102103
NotTriviallyDefaultConstructible>,
103104
"");
104105
auto b = Array<NotTriviallyDefaultConstructible, 5>::with_initializer(
105-
[i = 1]() mutable -> NotTriviallyDefaultConstructible { return {i++}; });
106+
[i = 1u]() mutable -> NotTriviallyDefaultConstructible { return {i++}; });
106107
static_assert(sizeof(b) == sizeof(NotTriviallyDefaultConstructible[5]));
107-
for (size_t i = 0; i < 5; ++i) {
108-
EXPECT_EQ(b.get(i).i, i + 1);
108+
for (auto i = 0_usize; i < 5_usize; i += 1_usize) {
109+
EXPECT_EQ(b.get(i).i, i + 1_usize);
109110
}
110111

111-
auto lvalue = [i = 1]() mutable { return i++; };
112-
auto c = Array<int, 5>::with_initializer(lvalue);
113-
static_assert(sizeof(c) == sizeof(int[5]));
114-
for (size_t i = 0; i < 5; ++i) {
115-
EXPECT_EQ(c.get(i), i + 1);
112+
auto lvalue = [i = 1u]() mutable { return i++; };
113+
auto c = Array<usize, 5>::with_initializer(lvalue);
114+
static_assert(sizeof(c) == sizeof(usize[5]));
115+
for (auto i = 0_usize; i < 5_usize; i += 1_usize) {
116+
EXPECT_EQ(c.get(i), i + 1_usize);
116117
}
117118

118-
static_assert(sizeof(Array<int, 5>::with_initializer([]() { return 1; })) ==
119-
sizeof(int[5]),
119+
static_assert(sizeof(Array<usize, 5>::with_initializer(
120+
[]() { return 1u; })) == sizeof(usize[5]),
120121
"");
121122
}
122123

123124
TEST(Array, WithValue) {
124-
auto a = Array<int, 5>::with_value(3);
125-
static_assert(sizeof(a) == sizeof(int[5]));
126-
for (size_t i = 0; i < 5; ++i) {
127-
EXPECT_EQ(a.get(i), 3);
125+
auto a = Array<usize, 5>::with_value(3u);
126+
static_assert(sizeof(a) == sizeof(usize[5]));
127+
for (auto i = 0_usize; i < 5_usize; i += 1_usize) {
128+
EXPECT_EQ(a.get(i), 3_usize);
128129
}
129130
}
130131

131132
TEST(Array, WithValues) {
132133
{
133-
auto a = Array<int, 5>::with_values(3, 4, 5, 6, 7);
134-
static_assert(sizeof(a) == sizeof(int[5]));
135-
for (size_t i = 0; i < 5; ++i) {
136-
EXPECT_EQ(a.get(i), 3 + i);
134+
auto a = Array<usize, 5>::with_values(3u, 4u, 5u, 6u, 7u);
135+
static_assert(sizeof(a) == sizeof(usize[5]));
136+
for (auto i = 0_usize; i < 5_usize; i += 1_usize) {
137+
EXPECT_EQ(a.get(i), 3_usize + i);
137138
}
138139
}
139140
{
140141
auto a = Array<u8, 5>::with_values(sus::into(3), sus::into(4), sus::into(5),
141142
sus::into(6), sus::into(7));
142143
static_assert(sizeof(a) == sizeof(u8[5]));
143144
for (auto i = 0_u8; i < 5_u8; i += 1_u8) {
144-
EXPECT_EQ(a.get(/* TODO: usize */ usize::from(i).primitive_value),
145-
3_u8 + i);
145+
EXPECT_EQ(a.get(usize::from(i)), 3_u8 + i);
146146
}
147147
}
148148
}
@@ -152,15 +152,15 @@ TEST(Array, Get) {
152152
constexpr auto r = []() constexpr {
153153
constexpr auto a =
154154
Array<int, 5>::with_initializer([i = 0]() mutable { return ++i; });
155-
return a.get(2);
155+
return a.get(2_usize);
156156
}
157157
();
158158
static_assert(std::same_as<decltype(r), const int>);
159159
EXPECT_EQ(3, r);
160160
}
161161
{
162162
auto a = Array<int, 5>::with_initializer([i = 0]() mutable { return ++i; });
163-
EXPECT_EQ(3, a.get(2));
163+
EXPECT_EQ(3, a.get(2_usize));
164164
}
165165
}
166166

@@ -169,16 +169,16 @@ TEST(Array, GetMut) {
169169
constexpr auto a = []() constexpr {
170170
auto a =
171171
Array<int, 5>::with_initializer([i = 0]() mutable { return ++i; });
172-
a.get_mut(0) = 101;
172+
a.get_mut(0_usize) = 101;
173173
return a;
174174
}
175175
();
176-
EXPECT_EQ(a.get(0), 101);
176+
EXPECT_EQ(a.get(0_usize), 101);
177177
}
178178
{
179179
auto a = Array<int, 5>::with_initializer([i = 0]() mutable { return ++i; });
180-
a.get_mut(0) = 101;
181-
EXPECT_EQ(a.get(0), 101);
180+
a.get_mut(0_usize) = 101;
181+
EXPECT_EQ(a.get(0_usize), 101);
182182
}
183183
}
184184

@@ -201,7 +201,7 @@ TEST(Array, Eq) {
201201
auto a = Array<int, 5>::with_initializer([i = 0]() mutable { return ++i; });
202202
auto b = Array<int, 5>::with_initializer([i = 0]() mutable { return ++i; });
203203
EXPECT_EQ(a, b);
204-
b.get_mut(3) += 1;
204+
b.get_mut(3_usize) += 1;
205205
EXPECT_NE(a, b);
206206
}
207207

@@ -210,15 +210,15 @@ TEST(Array, Ord) {
210210
auto b = Array<int, 5>::with_initializer([i = 0]() mutable { return ++i; });
211211
EXPECT_LE(a, b);
212212
EXPECT_GE(a, b);
213-
b.get_mut(3) += 1;
213+
b.get_mut(3_usize) += 1;
214214
EXPECT_LT(a, b);
215215
}
216216

217217
TEST(Array, StrongOrder) {
218218
auto a = Array<int, 5>::with_initializer([i = 0]() mutable { return ++i; });
219219
auto b = Array<int, 5>::with_initializer([i = 0]() mutable { return ++i; });
220220
EXPECT_EQ(std::strong_order(a, b), std::strong_ordering::equal);
221-
b.get_mut(3) += 1;
221+
b.get_mut(3_usize) += 1;
222222
EXPECT_EQ(std::strong_order(a, b), std::strong_ordering::less);
223223
}
224224

@@ -236,18 +236,22 @@ struct Weak final {
236236
};
237237

238238
TEST(Array, WeakOrder) {
239-
auto a = Array<Weak, 5>::with_initializer([i = 0]() mutable { return Weak(++i, 2); });
240-
auto b = Array<Weak, 5>::with_initializer([i = 0]() mutable { return Weak(++i, 2); });
239+
auto a = Array<Weak, 5>::with_initializer(
240+
[i = 0]() mutable { return Weak(++i, 2); });
241+
auto b = Array<Weak, 5>::with_initializer(
242+
[i = 0]() mutable { return Weak(++i, 2); });
241243
EXPECT_EQ(std::weak_order(a, b), std::weak_ordering::equivalent);
242-
b.get_mut(3).a += 1;
244+
b.get_mut(3_usize).a += 1;
243245
EXPECT_EQ(std::weak_order(a, b), std::weak_ordering::less);
244246
}
245247

246248
TEST(Array, PartialOrder) {
247-
auto a = Array<float, 5>::with_initializer([i = 0.f]() mutable { return ++i; });
248-
auto b = Array<float, 5>::with_initializer([i = 0.f]() mutable { return ++i; });
249+
auto a =
250+
Array<float, 5>::with_initializer([i = 0.f]() mutable { return ++i; });
251+
auto b =
252+
Array<float, 5>::with_initializer([i = 0.f]() mutable { return ++i; });
249253
EXPECT_EQ(std::partial_order(a, b), std::partial_ordering::equivalent);
250-
b.get_mut(3) += 1;
254+
b.get_mut(3_usize) += 1;
251255
EXPECT_EQ(std::partial_order(a, b), std::partial_ordering::less);
252256
}
253257

fn/callable.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,4 +79,9 @@ template <class T>
7979
concept CallableObjectMut = CallableObjectConst<T> ||
8080
__private::callable_mut(&T::operator());
8181

82+
template <class T, class R, class... Args>
83+
concept CallableReturns = FunctionPointerReturns<T, R, Args...> ||
84+
CallableObjectReturnsConst<T, R, Args...> ||
85+
CallableObjectReturnsMut<T, R, Args...>;
86+
8287
} // namespace sus::fn::callable

num/i32_unittest.cc

Lines changed: 24 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1833,85 +1833,53 @@ TEST(i32, FromLe) {
18331833
}
18341834

18351835
TEST(i32, ToBeBytes) {
1836-
if constexpr (sus::assertions::is_little_endian()) {
1837-
{
1838-
constexpr auto a = (0x12345678_i32).to_be_bytes();
1839-
EXPECT_EQ(a.get(0), 0x12_u8);
1840-
EXPECT_EQ(a.get(1), 0x34_u8);
1841-
EXPECT_EQ(a.get(2), 0x56_u8);
1842-
EXPECT_EQ(a.get(3), 0x78_u8);
1843-
}
1844-
{
1845-
auto a = (0x12345678_i32).to_be_bytes();
1846-
EXPECT_EQ(a.get(0), 0x12_u8);
1847-
EXPECT_EQ(a.get(1), 0x34_u8);
1848-
EXPECT_EQ(a.get(2), 0x56_u8);
1849-
EXPECT_EQ(a.get(3), 0x78_u8);
1850-
}
1851-
} else {
1852-
{
1853-
constexpr auto a = (0x12345678_i32).to_be_bytes();
1854-
EXPECT_EQ(a.get(0), 0x12_u8);
1855-
EXPECT_EQ(a.get(1), 0x34_u8);
1856-
EXPECT_EQ(a.get(2), 0x56_u8);
1857-
EXPECT_EQ(a.get(3), 0x78_u8);
1858-
}
1859-
{
1860-
auto a = (0x12345678_i32).to_be_bytes();
1861-
EXPECT_EQ(a.get(0), 0x12_u8);
1862-
EXPECT_EQ(a.get(1), 0x34_u8);
1863-
EXPECT_EQ(a.get(2), 0x56_u8);
1864-
EXPECT_EQ(a.get(3), 0x78_u8);
1865-
}
1836+
{
1837+
constexpr auto a = (0x12345678_i32).to_be_bytes();
1838+
EXPECT_EQ(a, (sus::Array<u8, 4>::with_values(0x12_u8, 0x34_u8, 0x56_u8,
1839+
0x78_u8)));
1840+
}
1841+
{
1842+
auto a = (0x12345678_i32).to_be_bytes();
1843+
EXPECT_EQ(a, (sus::Array<u8, 4>::with_values(0x12_u8, 0x34_u8, 0x56_u8,
1844+
0x78_u8)));
18661845
}
18671846
}
18681847

18691848
TEST(i32, ToLeBytes) {
1870-
if constexpr (sus::assertions::is_big_endian()) {
1849+
{
18711850
constexpr auto a = (0x12345678_i32).to_le_bytes();
1872-
EXPECT_EQ(a.get(0), 0x78_u8);
1873-
EXPECT_EQ(a.get(1), 0x56_u8);
1874-
EXPECT_EQ(a.get(2), 0x34_u8);
1875-
EXPECT_EQ(a.get(3), 0x12_u8);
1876-
} else {
1851+
EXPECT_EQ(a, (sus::Array<u8, 4>::with_values(0x78_u8, 0x56_u8, 0x34_u8,
1852+
0x12_u8)));
1853+
}
1854+
{
18771855
auto a = (0x12345678_i32).to_le_bytes();
1878-
EXPECT_EQ(a.get(0), 0x78_u8);
1879-
EXPECT_EQ(a.get(1), 0x56_u8);
1880-
EXPECT_EQ(a.get(2), 0x34_u8);
1881-
EXPECT_EQ(a.get(3), 0x12_u8);
1856+
EXPECT_EQ(a, (sus::Array<u8, 4>::with_values(0x78_u8, 0x56_u8, 0x34_u8,
1857+
0x12_u8)));
18821858
}
18831859
}
18841860

18851861
TEST(i32, ToNeBytes) {
18861862
if constexpr (sus::assertions::is_big_endian()) {
18871863
{
18881864
constexpr auto a = (0x12345678_i32).to_ne_bytes();
1889-
EXPECT_EQ(a.get(0), 0x12_u8);
1890-
EXPECT_EQ(a.get(1), 0x34_u8);
1891-
EXPECT_EQ(a.get(2), 0x56_u8);
1892-
EXPECT_EQ(a.get(3), 0x78_u8);
1865+
EXPECT_EQ(a, (sus::Array<u8, 4>::with_values(0x12_u8, 0x34_u8, 0x56_u8,
1866+
0x78_u8)));
18931867
}
18941868
{
18951869
auto a = (0x12345678_i32).to_ne_bytes();
1896-
EXPECT_EQ(a.get(0), 0x12_u8);
1897-
EXPECT_EQ(a.get(1), 0x34_u8);
1898-
EXPECT_EQ(a.get(2), 0x56_u8);
1899-
EXPECT_EQ(a.get(3), 0x78_u8);
1870+
EXPECT_EQ(a, (sus::Array<u8, 4>::with_values(0x12_u8, 0x34_u8, 0x56_u8,
1871+
0x78_u8)));
19001872
}
19011873
} else {
19021874
{
19031875
constexpr auto a = (0x12345678_i32).to_ne_bytes();
1904-
EXPECT_EQ(a.get(0), 0x78_u8);
1905-
EXPECT_EQ(a.get(1), 0x56_u8);
1906-
EXPECT_EQ(a.get(2), 0x34_u8);
1907-
EXPECT_EQ(a.get(3), 0x12_u8);
1876+
EXPECT_EQ(a, (sus::Array<u8, 4>::with_values(0x78_u8, 0x56_u8, 0x34_u8,
1877+
0x12_u8)));
19081878
}
19091879
{
19101880
auto a = (0x12345678_i32).to_ne_bytes();
1911-
EXPECT_EQ(a.get(0), 0x78_u8);
1912-
EXPECT_EQ(a.get(1), 0x56_u8);
1913-
EXPECT_EQ(a.get(2), 0x34_u8);
1914-
EXPECT_EQ(a.get(3), 0x12_u8);
1881+
EXPECT_EQ(a, (sus::Array<u8, 4>::with_values(0x78_u8, 0x56_u8, 0x34_u8,
1882+
0x12_u8)));
19151883
}
19161884
}
19171885
}

0 commit comments

Comments
 (0)