Skip to content

Commit beeb9b8

Browse files
committed
refactor(allocation-value): reduced duplications
1 parent c664e86 commit beeb9b8

File tree

7 files changed

+108
-121
lines changed

7 files changed

+108
-121
lines changed

include/stdsharp/algorithm/algorithm.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,8 +154,7 @@ namespace stdsharp
154154
constexpr move_n_result<In, Out>
155155
operator()(In in, const std::iter_difference_t<In> n, Out out) const
156156
{
157-
auto&& r = std::ranges::
158-
move(std::counted_iterator{cpp_move(in), n}, std::default_sentinel, cpp_move(out));
157+
auto&& r = std::ranges::copy_n(std::move_iterator{cpp_move(in)}, n, cpp_move(out));
159158

160159
return {cpp_move(r).in.base(), cpp_move(r).out};
161160
}

include/stdsharp/concepts/object.h

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,11 @@ namespace stdsharp
2626
template<typename T>
2727
concept trivial_move_assignable = std::is_trivially_move_assignable_v<T>;
2828

29-
template<typename T, typename U>
30-
concept assignable = std::is_assignable_v<T, U>;
31-
32-
template<typename T, typename U>
33-
concept nothrow_assignable = std::is_nothrow_assignable_v<T, U>;
34-
3529
template<typename T>
36-
concept move_assignable = std::is_move_assignable_v<T>;
30+
concept move_assignable = std::assignable_from<T&, T>;
3731

3832
template<typename T>
39-
concept copy_assignable = std::is_copy_assignable_v<T>;
33+
concept copy_assignable = std::assignable_from<T&, const T&>;
4034

4135
template<typename T, typename U>
4236
concept nothrow_convertible_to = std::is_nothrow_convertible_v<T, U>;
@@ -45,7 +39,7 @@ namespace stdsharp
4539
concept inheritable = class_<T> && !final<T>;
4640

4741
template<typename T, typename U>
48-
concept assignable_to = assignable<U, T>;
42+
concept assignable_to = std::assignable_from<U, T>;
4943

5044
template<typename From, typename To>
5145
concept explicitly_convertible = requires(From&& v) { static_cast<To>(cpp_forward(v)); };
@@ -167,13 +161,14 @@ namespace stdsharp
167161
concept nothrow_copy_constructible = std::is_nothrow_copy_constructible_v<T>;
168162

169163
template<typename T, typename U>
170-
concept nothrow_assignable_from = std::is_nothrow_assignable_v<T, U>;
164+
concept nothrow_assignable_from = std::assignable_from<T, U> &&
165+
std::is_nothrow_assignable_v<T, U>;
171166

172167
template<typename T>
173-
concept nothrow_copy_assignable = std::is_nothrow_copy_assignable_v<T>;
168+
concept nothrow_copy_assignable = copy_assignable<T> && std::is_nothrow_copy_assignable_v<T>;
174169

175170
template<typename T>
176-
concept nothrow_move_assignable = std::is_nothrow_move_assignable_v<T>;
171+
concept nothrow_move_assignable = move_assignable<T> && std::is_nothrow_move_assignable_v<T>;
177172

178173
template<typename T, typename U>
179174
concept nothrow_swappable_with =

include/stdsharp/functional/operations.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,22 +25,22 @@ namespace stdsharp
2525
struct assign
2626
{
2727
template<typename T, typename U = T>
28-
requires assignable<T&, U>
28+
requires std::assignable_from<T&, U>
2929
constexpr decltype(auto) operator()(T& left, U&& right) const
30-
noexcept(nothrow_assignable<T&, U>)
30+
noexcept(nothrow_assignable_from<T&, U>)
3131
{
3232
return left = cpp_forward(right);
3333
}
3434
};
3535

3636
struct assign_by_construct
3737
{
38-
template<typename T, typename... U, typename ActualT = std::remove_reference_t<T>>
39-
requires std::constructible_from<ActualT, U...>
38+
template<typename T, typename... U, typename DecayT = std::remove_reference_t<T>>
39+
requires std::constructible_from<DecayT, U...>
4040
constexpr decltype(auto) operator()(T& left, U&&... right) const
41-
noexcept(noexcept(left = ActualT{cpp_forward(right)...}))
41+
noexcept(noexcept(left = DecayT{cpp_forward(right)...}))
4242
{
43-
return left = ActualT{cpp_forward(right)...};
43+
return left = DecayT{cpp_forward(right)...};
4444
}
4545
};
4646
}
Lines changed: 89 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
#pragma once
22

3-
#include "../algorithm/algorithm.h"
43
#include "allocation_traits.h"
54
#include "launder_iterator.h"
65

6+
#include <algorithm>
7+
78
namespace stdsharp::details
89
{
910
template<typename Allocator, typename T>
@@ -20,21 +21,33 @@ namespace stdsharp::details
2021
static constexpr auto data = allocation_traits::template data<T>;
2122
static constexpr auto get = allocation_traits::template get<T>;
2223

23-
constexpr void size_validate(this const auto& t, const auto& allocation) noexcept
24+
template<typename>
25+
struct forward_value;
26+
27+
template<allocation<Allocator> Allocation>
28+
struct forward_value<Allocation>
2429
{
25-
Expects(
26-
allocation.size() * sizeof(typename allocation_traits::value_type) >= t.value_size()
27-
);
28-
}
30+
using type = T&&;
31+
};
32+
33+
template<callocation<Allocator> Allocation>
34+
struct forward_value<Allocation>
35+
{
36+
using type = const T&;
37+
};
2938

30-
constexpr void size_validate(
31-
this const auto& t,
32-
const auto& src_allocation,
33-
const auto& dst_allocation
34-
) noexcept
39+
template<typename Allocation>
40+
using forward_value_t = forward_value<Allocation>::type;
41+
42+
constexpr void size_validate(this const auto& t, const auto&... allocations) noexcept
3543
{
36-
t.size_validate(src_allocation);
37-
t.size_validate(dst_allocation);
44+
( //
45+
Expects(
46+
allocations.size() * sizeof(typename allocation_traits::value_type) >=
47+
t.value_size()
48+
),
49+
...
50+
);
3851
}
3952

4053
static constexpr struct default_construct_t
@@ -60,6 +73,9 @@ namespace stdsharp
6073
using m_base::data;
6174
using m_base::get;
6275

76+
template<typename Allocation>
77+
using forward_value_t = m_base::template forward_value_t<Allocation>;
78+
6379
static constexpr auto always_equal = true;
6480

6581
[[nodiscard]] static constexpr auto value_size() noexcept { return sizeof(T); }
@@ -69,6 +85,14 @@ namespace stdsharp
6985
private:
7086
using typename m_base::ctor;
7187
using typename m_base::dtor;
88+
using m_base::size_validate;
89+
90+
template<typename Allocation>
91+
[[nodiscard]] constexpr decltype(auto) forward_value(const Allocation& src_allocation) const noexcept
92+
{
93+
size_validate(src_allocation);
94+
return static_cast<forward_value_t<Allocation>>(get(src_allocation));
95+
}
7296

7397
public:
7498
constexpr void operator()(
@@ -78,58 +102,39 @@ namespace stdsharp
78102
) const noexcept(nothrow_invocable<ctor, allocator_type&, T*>)
79103
requires std::invocable<ctor, allocator_type&, T*>
80104
{
81-
this->size_validate(allocation);
105+
size_validate(allocation);
82106
ctor{}(allocator, data(allocation));
83107
}
84108

109+
template<typename SrcAllocation, typename Value = forward_value_t<SrcAllocation>>
110+
requires std::invocable<ctor, allocator_type&, T*, Value>
85111
constexpr void operator()(
86112
allocator_type& allocator,
87-
const callocation<Allocator> auto& src_allocation,
113+
const SrcAllocation& src_allocation,
88114
const allocation<Allocator> auto& dst_allocation
89-
) const noexcept(nothrow_invocable<ctor, allocator_type&, T*, const T&>)
90-
requires std::invocable<ctor, allocator_type&, T*, const T&>
115+
) const noexcept(nothrow_invocable<ctor, allocator_type&, T*, Value>)
91116
{
92-
this->size_validate(src_allocation, dst_allocation);
93-
ctor{}(allocator, data(dst_allocation), get(src_allocation));
117+
size_validate(dst_allocation);
118+
ctor{}(allocator, data(dst_allocation), forward_value(src_allocation));
94119
}
95120

121+
template<typename Allocation, typename Value = forward_value_t<Allocation>>
96122
constexpr void operator()(
97-
allocator_type& allocator,
98-
const allocation<Allocator> auto& src_allocation,
99-
const allocation<Allocator> auto& dst_allocation
100-
) const noexcept(nothrow_invocable<ctor, allocator_type&, T*, T>)
101-
requires std::invocable<ctor, allocator_type&, T*, T>
102-
{
103-
this->size_validate(src_allocation, dst_allocation);
104-
ctor{}(allocator, data(dst_allocation), cpp_move(get(src_allocation)));
105-
}
106-
107-
constexpr void operator()(
108-
const callocation<Allocator> auto& src_allocation,
123+
const Allocation& src_allocation,
109124
const allocation<Allocator> auto& dst_allocation
110-
) const noexcept(nothrow_copy_assignable<T>)
111-
requires copy_assignable<T>
125+
) const noexcept(nothrow_assignable_from<T&, Value>)
126+
requires std::assignable_from<T&, Value>
112127
{
113-
this->size_validate(src_allocation, dst_allocation);
114-
get(dst_allocation) = get(src_allocation);
115-
}
116-
117-
constexpr void operator()(
118-
const allocation<Allocator> auto& src_allocation,
119-
const allocation<Allocator> auto& dst_allocation
120-
) const noexcept(nothrow_move_assignable<T>)
121-
requires move_assignable<T>
122-
{
123-
this->size_validate(src_allocation, dst_allocation);
124-
get(dst_allocation) = cpp_move(get(src_allocation));
128+
size_validate(dst_allocation);
129+
get(dst_allocation) = forward_value(src_allocation);
125130
}
126131

127132
constexpr void operator()(
128133
allocator_type& allocator,
129134
const allocation<Allocator> auto& allocation
130135
) const noexcept
131136
{
132-
this->size_validate(allocation);
137+
size_validate(allocation);
133138
dtor{}(allocator, data(allocation));
134139
}
135140
};
@@ -154,17 +159,34 @@ namespace stdsharp
154159
using typename m_base::ctor;
155160
using typename m_base::dtor;
156161
using size_t = std::size_t;
162+
using m_base::size_validate;
157163

158164
size_t size_;
159165

160166
[[nodiscard]] constexpr auto launder_begin(const auto& allocation) const noexcept
161167
{
168+
size_validate(allocation);
162169
return launder_iterator{data(allocation)};
163170
}
164171

165-
[[nodiscard]] constexpr auto value_rng(const auto& allocation) const noexcept
172+
[[nodiscard]] constexpr auto
173+
forward_launder_begin(const callocation<Allocator> auto& allocation) const noexcept
174+
{
175+
return launder_begin(allocation);
176+
}
177+
178+
[[nodiscard]] constexpr auto
179+
forward_launder_begin(const allocation<Allocator> auto& allocation) const noexcept
180+
{
181+
return std::move_iterator{launder_begin(allocation)};
182+
}
183+
184+
template<typename Allocation>
185+
using forward_value_t = m_base::template forward_value_t<Allocation>;
186+
187+
[[nodiscard]] constexpr auto forward_rng(const auto& allocation) const noexcept
166188
{
167-
return std::views::counted(launder_begin(allocation), size());
189+
return std::views::counted(forward_launder_begin(allocation), size());
168190
}
169191

170192
public:
@@ -183,81 +205,49 @@ namespace stdsharp
183205
) const noexcept(nothrow_invocable<ctor, allocator_type&, T*>)
184206
requires std::invocable<ctor, allocator_type&, T*>
185207
{
186-
this->size_validate(allocation);
187-
188-
auto&& p = data(allocation);
189-
const auto count = size();
190-
for(size_t i = 0; i < count; ++i, ++p) ctor{}(allocator, p);
191-
}
192-
193-
constexpr void operator()(
194-
allocator_type& allocator,
195-
const callocation<Allocator> auto& src_allocation,
196-
const allocation<Allocator> auto& dst_allocation
197-
) const noexcept(nothrow_invocable<ctor, allocator_type&, T*, const T&>)
198-
requires std::invocable<ctor, allocator_type&, T*, const T&>
199-
{
200-
this->size_validate(src_allocation, dst_allocation);
201-
202-
auto&& dst_begin = data(dst_allocation);
203-
const auto& src_begin = launder_begin(src_allocation);
204-
const auto count = size();
205-
206-
for(size_t i = 0; i < count; ++i, ++dst_begin)
207-
ctor{}(allocator, dst_begin, src_begin[i]);
208+
size_validate(allocation);
209+
auto begin = data(allocation);
210+
for(const auto end = begin + size(); begin < end; ++begin) ctor{}(allocator, begin);
208211
}
209212

213+
template<typename Allocation, typename Value = forward_value_t<Allocation>>
210214
constexpr void operator()(
211215
allocator_type& allocator,
212-
const allocation<Allocator> auto& src_allocation,
216+
const Allocation& src_allocation,
213217
const allocation<Allocator> auto& dst_allocation
214-
) const noexcept(nothrow_invocable<ctor, allocator_type&, T*, T>)
215-
requires std::invocable<ctor, allocator_type&, T*, T>
218+
) const noexcept(nothrow_invocable<ctor, allocator_type&, T*, Value>)
219+
requires std::invocable<ctor, allocator_type&, T*, Value>
216220
{
217-
this->size_validate(src_allocation, dst_allocation);
221+
size_validate(dst_allocation);
218222

219-
auto&& dst_begin = data(dst_allocation);
220-
const auto& src_begin = launder_begin(src_allocation);
223+
const auto& dst_begin = data(dst_allocation);
224+
const auto& src_begin = forward_launder_begin(src_allocation);
221225
const auto count = size();
222226

223-
for(size_t i = 0; i < count; ++i, ++dst_begin)
224-
ctor{}(allocator, dst_begin, cpp_move(src_begin[i]));
227+
for(size_t i = 0; i < count; ++i) ctor{}(allocator, dst_begin[i], src_begin[i]);
225228
}
226229

230+
template<typename Allocation, typename Value = forward_value_t<Allocation>>
227231
constexpr void operator()(
228-
const callocation<Allocator> auto& src_allocation,
232+
const Allocation& src_allocation,
229233
const allocation<Allocator> auto& dst_allocation
230-
) const noexcept(nothrow_copy_assignable<T>)
231-
requires copy_assignable<T>
234+
) const noexcept(nothrow_assignable_from<T, Value>)
235+
requires std::assignable_from<T, Value>
232236
{
233-
this->size_validate(src_allocation, dst_allocation);
234-
std::ranges::copy_n( //
237+
std::ranges::copy_n(
235238
launder_begin(src_allocation),
236239
size(),
237-
launder_begin(dst_allocation)
240+
forward_launder_begin(dst_allocation)
238241
);
239242
}
240243

241-
constexpr void operator()(
242-
const allocation<Allocator> auto& src_allocation,
243-
const allocation<Allocator> auto& dst_allocation
244-
) const noexcept(nothrow_move_assignable<T>)
245-
requires move_assignable<T>
246-
{
247-
this->size_validate(src_allocation, dst_allocation);
248-
move_n(launder_begin(src_allocation), size(), launder_begin(dst_allocation));
249-
}
250-
251244
constexpr void operator()(
252245
allocator_type& allocator,
253246
const allocation<Allocator> auto& allocation
254247
) const noexcept
255248
{
256-
this->size_validate(allocation);
257-
258-
auto&& iter = launder_begin(allocation);
259-
const auto count = size();
260-
for(size_t i = 0; i < count; ++i, ++iter) dtor{}(allocator, iter.data());
249+
auto&& begin = launder_begin(allocation);
250+
for(const auto& end = begin + size(); begin < end; ++begin) dtor{}(allocator, begin);
261251
}
262252
};
263253
}

include/stdsharp/memory/launder_iterator.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ namespace stdsharp
2626

2727
[[nodiscard]] constexpr auto data() const noexcept { return std::launder(ptr_); }
2828

29+
[[nodiscard]] constexpr operator T*() const noexcept { return data(); }
30+
2931
[[nodiscard]] constexpr decltype(auto) operator[](const difference_type diff) const noexcept
3032
{
3133
assert_not_null(ptr_);

0 commit comments

Comments
 (0)