Skip to content

Commit a6bcc85

Browse files
committed
refactor(allocation-value): reduced duplication
1 parent 8ad5ed0 commit a6bcc85

File tree

4 files changed

+90
-102
lines changed

4 files changed

+90
-102
lines changed

.clang-tidy

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ Checks: # enabled
3838
-*-reserved-identifier,
3939
-cert-dcl58-cpp,
4040
-*-avoid-nested-conditional-operator,
41-
-*-inc-dec-in-conditions'
41+
-*-inc-dec-in-conditions,
42+
-*-pointer-arithmetic'
4243
# disabled alias
4344
- '-bugprone-narrowing-conversions,
4445
-cert-con36-c,

include/stdsharp/memory/allocation_value.h

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,9 @@ namespace stdsharp::details
6060
return allocation_traits::template get<T>(allocation);
6161
}
6262

63-
static constexpr struct default_construct_t
63+
static constexpr struct construct_t
6464
{
65-
} default_construct{};
65+
} construct{};
6666
};
6767
}
6868

@@ -101,14 +101,16 @@ namespace stdsharp
101101
}
102102

103103
public:
104+
template<typename... Args>
104105
constexpr void operator()(
105106
allocator_type& allocator,
106107
const allocation<Allocator> auto& allocation,
107-
const m_base::default_construct_t /*unused*/
108-
) const noexcept(nothrow_invocable<ctor, allocator_type&, T*>)
109-
requires std::invocable<ctor, allocator_type&, T*>
108+
const m_base::construct_t /*unused*/,
109+
Args&&... args
110+
) const noexcept(nothrow_invocable<ctor, allocator_type&, T*, Args...>)
111+
requires std::invocable<ctor, allocator_type&, T*, Args...>
110112
{
111-
ctor{}(allocator, data(allocation));
113+
ctor{}(allocator, data(allocation), cpp_forward(args)...);
112114
}
113115

114116
template<typename SrcAllocation, typename Value = forward_value_t<SrcAllocation>>
@@ -196,15 +198,36 @@ namespace stdsharp
196198

197199
[[nodiscard]] bool operator==(const allocation_value&) const = default;
198200

201+
template<typename... Args>
199202
constexpr void operator()(
200203
allocator_type& allocator,
201204
const allocation<Allocator> auto& allocation,
202-
const m_base::default_construct_t /*unused*/
203-
) const noexcept(nothrow_invocable<ctor, allocator_type&, T*>)
204-
requires std::invocable<ctor, allocator_type&, T*>
205+
const m_base::construct_t /*unused*/,
206+
Args&&... args
207+
) const noexcept(nothrow_invocable<ctor, allocator_type&, T*, Args...>)
208+
requires std::invocable<ctor, allocator_type&, T*, Args...>
205209
{
206210
auto begin = m_base::data(allocation);
207-
for(const auto end = begin + size(); begin < end; ++begin) ctor{}(allocator, begin);
211+
for(const auto end = begin + size(); begin < end; ++begin)
212+
ctor{}(allocator, begin, cpp_forward(args)...);
213+
}
214+
215+
static constexpr struct iter_construct_t
216+
{
217+
} iter_construct{};
218+
219+
template<std::forward_iterator Iter, typename ValueT = std::iter_reference_t<Iter>>
220+
constexpr void operator()(
221+
allocator_type& allocator,
222+
const allocation<Allocator> auto& allocation,
223+
const iter_construct_t /*unused*/,
224+
Iter iter
225+
) const noexcept(nothrow_invocable<ctor, allocator_type&, T*, ValueT>)
226+
requires std::invocable<ctor, allocator_type&, T*, ValueT>
227+
{
228+
auto begin = m_base::data(allocation);
229+
for(const auto end = begin + size(); begin < end; ++begin, ++iter)
230+
ctor{}(allocator, begin, *iter);
208231
}
209232

210233
template<typename Allocation, typename Value = forward_value_t<Allocation>>
@@ -229,7 +252,7 @@ namespace stdsharp
229252
) const noexcept(nothrow_assignable_from<T&, Value>)
230253
requires std::assignable_from<T&, Value>
231254
{
232-
std::ranges::copy_n(forward_data(dst_allocation), size(), data(src_allocation));
255+
std::ranges::copy_n(forward_data(src_allocation), size(), data(dst_allocation));
233256
}
234257

235258
constexpr void operator()(

include/stdsharp/memory/launder_iterator.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
namespace stdsharp
99
{
10-
template<typename T> // NOLINTBEGIN(*-pointer-arithmetic)
10+
template<typename T>
1111
class launder_iterator : public basic_iterator
1212
{
1313
T* ptr_;
@@ -35,7 +35,7 @@ namespace stdsharp
3535
}
3636

3737
using basic_iterator::operator[];
38-
}; // NOLINTEND(*-pointer-arithmetic)
38+
};
3939

4040
template<typename T>
4141
launder_iterator(T*) -> launder_iterator<T>;

tests/src/memory/allocation_value.cpp

Lines changed: 52 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -4,157 +4,121 @@
44

55
STDSHARP_TEST_NAMESPACES;
66

7-
SCENARIO("vector allocation value", "[memory][allocation_value]")
7+
struct vector_data
88
{
9+
using allocation_value_type = vector<int>;
910
using allocator_type = std::allocator<stdsharp::byte>;
1011
using allocation_traits = allocation_traits<allocator_type>;
11-
using allocator_traits = allocation_traits::allocator_traits;
12-
using allocation_value_t = allocation_value<allocator_type, vector<int>>;
12+
using allocation_value_t =
13+
allocation_value<allocator_type, allocation_value_type>;
1314

14-
allocator_type allocator;
15-
allocation_value_t allocation_value;
16-
const auto allocation_1 = allocation_traits::allocate(allocator, sizeof(vector<int>));
17-
allocation_traits::callocation_result callocation_1 = allocation_1;
18-
const auto allocation_2 = allocation_traits::allocate(allocator, sizeof(vector<int>));
19-
const vector<int> seq{1, 2, 3};
15+
static constexpr array<int, 3> data{1, 2, 3};
16+
static constexpr std::ranges::empty_view<int> default_value{};
17+
static constexpr size_t allocation_size = sizeof(allocation_value_type);
18+
static constexpr allocation_value_t allocation_value{};
2019

21-
WHEN("default construct")
20+
static constexpr void set_value(const auto& allocation_value, const auto& allocation)
2221
{
23-
allocation_value(allocator, allocation_1, {});
24-
25-
THEN("value is 0")
26-
{
27-
REQUIRE_THAT(
28-
allocation_value.get(allocation_1),
29-
Catch::Matchers::RangeEquals(vector<int>{})
30-
);
31-
}
32-
33-
THEN("set the value to int sequence")
34-
{
35-
allocation_value.get(allocation_1) = seq;
36-
REQUIRE_THAT(allocation_value.get(allocation_1), Catch::Matchers::RangeEquals(seq));
37-
}
38-
39-
allocation_value(allocator, allocation_1);
22+
allocation_value.get(allocation) = {data.begin(), data.end()};
4023
}
4124

42-
WHEN("constructs and set value to seq")
25+
static constexpr void
26+
construct_value(auto& allocator, const auto& allocation_value, const auto& allocation)
4327
{
44-
allocation_value(allocator, allocation_1, {});
45-
allocation_value.get(allocation_1) = seq;
46-
47-
THEN("copy construct")
48-
{
49-
allocation_value(allocator, callocation_1, allocation_2);
50-
THEN("value is seq")
51-
{
52-
REQUIRE_THAT(allocation_value.get(allocation_2), Catch::Matchers::RangeEquals(seq));
53-
}
54-
allocation_value(allocator, allocation_2);
55-
}
56-
57-
THEN("move construct")
58-
{
59-
allocation_value(allocator, allocation_1, allocation_2);
60-
REQUIRE_THAT(allocation_value.get(allocation_2), Catch::Matchers::RangeEquals(seq));
61-
allocation_value(allocator, allocation_2);
62-
}
28+
allocation_value(allocator, allocation, {}, data.begin(), data.end());
29+
}
30+
};
6331

64-
THEN("copy assign")
65-
{
66-
allocation_value(allocator, allocation_2, {});
67-
allocation_value(callocation_1, allocation_2);
68-
REQUIRE_THAT(allocation_value.get(allocation_2), Catch::Matchers::RangeEquals(seq));
69-
allocation_value(allocator, allocation_2);
70-
}
32+
struct array_data
33+
{
34+
using allocation_value_type = int[]; // NOLINT(*-arrays)
35+
using allocator_type = std::allocator<stdsharp::byte>;
36+
using allocation_traits = allocation_traits<allocator_type>;
37+
using allocation_value_t =
38+
allocation_value<allocator_type, allocation_value_type>;
7139

72-
THEN("move assign")
73-
{
74-
allocation_value(allocator, allocation_2, {});
75-
allocation_value(allocation_1, allocation_2);
76-
REQUIRE_THAT(allocation_value.get(allocation_2), Catch::Matchers::RangeEquals(seq));
77-
allocation_value(allocator, allocation_2);
78-
}
40+
static constexpr array<int, 3> data{1, 2, 3};
41+
static constexpr std::ranges::repeat_view<int, int> default_value{0, 3};
42+
static constexpr size_t allocation_size = data.size() * sizeof(int);
43+
static constexpr allocation_value_t allocation_value{data.size()};
7944

80-
allocation_value(allocator, allocation_1);
45+
static constexpr void set_value(const auto& allocation_value, const auto& allocation)
46+
{
47+
std::ranges::copy(data, allocation_value.data(allocation));
8148
}
8249

83-
allocation_traits::deallocate(allocator, array{allocation_1, allocation_2});
84-
}
50+
static constexpr void
51+
construct_value(auto& allocator, const auto& allocation_value, const auto& allocation)
52+
{
53+
allocation_value(allocator, allocation, {}, data.begin());
54+
}
55+
};
8556

86-
SCENARIO("int array allocation value", "[memory][allocation_value]")
57+
TEMPLATE_TEST_CASE("Scenario: allocation value", "[memory][allocation_value]", vector_data, array_data)
8758
{
88-
using allocator_type = std::allocator<int>;
89-
using allocation_traits = allocation_traits<allocator_type>;
90-
using allocator_traits = allocation_traits::allocator_traits;
91-
using allocation_value_t = allocation_value<allocator_type, int[]>; // NOLINT(*-arrays)
92-
93-
allocator_type allocator;
94-
allocation_value_t allocation_value{3};
95-
const auto allocation_1 =
96-
allocation_traits::allocate(allocator, allocation_value.size() * sizeof(int));
97-
allocation_traits::callocation_result callocation_1 = allocation_1;
98-
const auto allocation_2 =
99-
allocation_traits::allocate(allocator, allocation_value.size() * sizeof(int));
100-
const int seq[3]{1, 2, 3}; // NOLINT(*-arrays)
59+
using allocation_traits = TestType::allocation_traits;
60+
61+
typename TestType::allocator_type allocator;
62+
auto allocation_value = TestType::allocation_value;
63+
const auto allocation_1 = allocation_traits::allocate(allocator, TestType::allocation_size);
64+
typename allocation_traits::callocation_result callocation_1 = allocation_1;
65+
const auto allocation_2 = allocation_traits::allocate(allocator, TestType::allocation_size);
10166

10267
WHEN("default construct")
10368
{
10469
allocation_value(allocator, allocation_1, {});
10570

106-
THEN("value is 0")
71+
THEN("value is default")
10772
{
10873
REQUIRE_THAT(
10974
allocation_value.get(allocation_1),
110-
Catch::Matchers::RangeEquals(vector<int>{})
75+
Catch::Matchers::RangeEquals(TestType::default_value)
11176
);
11277
}
11378

11479
THEN("set the value to int sequence")
11580
{
116-
std::ranges::copy(seq, allocation_value.data(allocation_1));
117-
REQUIRE_THAT(allocation_value.get(allocation_1), Catch::Matchers::RangeEquals(seq));
81+
TestType::set_value(allocation_value, allocation_1);
82+
REQUIRE_THAT(allocation_value.get(allocation_1), Catch::Matchers::RangeEquals(TestType::data));
11883
}
11984

12085
allocation_value(allocator, allocation_1);
12186
}
12287

12388
WHEN("constructs and set value to seq")
12489
{
125-
allocation_value(allocator, allocation_1, {});
126-
std::ranges::copy(seq, allocation_value.data(allocation_1));
90+
TestType::construct_value(allocator, allocation_value, allocation_1);
12791

12892
THEN("copy construct")
12993
{
13094
allocation_value(allocator, callocation_1, allocation_2);
13195
THEN("value is seq")
13296
{
133-
REQUIRE_THAT(allocation_value.get(allocation_2), Catch::Matchers::RangeEquals(seq));
97+
REQUIRE_THAT(allocation_value.get(allocation_2), Catch::Matchers::RangeEquals(TestType::data));
13498
}
13599
allocation_value(allocator, allocation_2);
136100
}
137101

138102
THEN("move construct")
139103
{
140104
allocation_value(allocator, allocation_1, allocation_2);
141-
REQUIRE_THAT(allocation_value.get(allocation_2), Catch::Matchers::RangeEquals(seq));
105+
REQUIRE_THAT(allocation_value.get(allocation_2), Catch::Matchers::RangeEquals(TestType::data));
142106
allocation_value(allocator, allocation_2);
143107
}
144108

145109
THEN("copy assign")
146110
{
147111
allocation_value(allocator, allocation_2, {});
148112
allocation_value(callocation_1, allocation_2);
149-
REQUIRE_THAT(allocation_value.get(allocation_2), Catch::Matchers::RangeEquals(seq));
113+
REQUIRE_THAT(allocation_value.get(allocation_2), Catch::Matchers::RangeEquals(TestType::data));
150114
allocation_value(allocator, allocation_2);
151115
}
152116

153117
THEN("move assign")
154118
{
155119
allocation_value(allocator, allocation_2, {});
156120
allocation_value(allocation_1, allocation_2);
157-
REQUIRE_THAT(allocation_value.get(allocation_2), Catch::Matchers::RangeEquals(seq));
121+
REQUIRE_THAT(allocation_value.get(allocation_2), Catch::Matchers::RangeEquals(TestType::data));
158122
allocation_value(allocator, allocation_2);
159123
}
160124

0 commit comments

Comments
 (0)