1
1
module ;
2
2
3
+ #include < bounded/conditional.hpp>
3
4
#include < operators/forward.hpp>
4
5
5
6
export module containers.trivial_inplace_function;
@@ -131,10 +132,13 @@ struct trivial_inplace_function_impl {
131
132
}
132
133
}
133
134
135
+ constexpr explicit trivial_inplace_function_impl (bounded::tombstone_tag):
136
+ m_function_indirection(nullptr )
137
+ {
138
+ }
139
+
140
+ friend bounded::tombstone_traits<trivial_inplace_function_impl>;
134
141
public:
135
- // I would prefer that this not be default constructible. However, that
136
- // would mean it could not be stored in a constexpr static_vector
137
- trivial_inplace_function_impl () = default ;
138
142
139
143
constexpr trivial_inplace_function_impl (trivially_storable<capacity, alignment, R, Args...> auto function):
140
144
m_storage(make_storage(function)),
@@ -158,6 +162,25 @@ struct trivial_inplace_function_impl {
158
162
}
159
163
};
160
164
165
+ } // namespace containers
166
+
167
+ template <bool is_const, std::size_t capacity, std::size_t alignment, typename R, typename ... Args>
168
+ struct bounded ::tombstone_traits<containers::trivial_inplace_function_impl<is_const, capacity, alignment, R, Args...>> {
169
+ private:
170
+ using T = containers::trivial_inplace_function_impl<is_const, capacity, alignment, R, Args...>;
171
+ public:
172
+ static constexpr auto spare_representations = 1_bi;
173
+
174
+ static constexpr auto make (bounded::constant_t <0 >) noexcept {
175
+ return T (bounded::tombstone_tag ());
176
+ }
177
+ static constexpr auto index (T const & value) noexcept {
178
+ return BOUNDED_CONDITIONAL (value.m_function_indirection , -1_bi, 0_bi);
179
+ }
180
+ };
181
+
182
+ namespace containers {
183
+
161
184
// If your function type is convertible to a function pointer, calling through
162
185
// the function must have the same semantics as calling through the function
163
186
// pointer.
@@ -174,8 +197,13 @@ struct trivial_inplace_function<R(Args...), capacity, alignment> :
174
197
{
175
198
private:
176
199
using base = trivial_inplace_function_impl<false , capacity, alignment, R, Args...>;
200
+ friend bounded::tombstone_traits<trivial_inplace_function>;
177
201
public:
178
202
using base::base;
203
+ constexpr explicit trivial_inplace_function (base && b) noexcept :
204
+ base(std::move(b))
205
+ {
206
+ }
179
207
using base::operator ();
180
208
};
181
209
@@ -185,83 +213,30 @@ struct trivial_inplace_function<R(Args...) const, capacity, alignment> :
185
213
{
186
214
private:
187
215
using base = trivial_inplace_function_impl<true , capacity, alignment, R, Args...>;
216
+ friend bounded::tombstone_traits<trivial_inplace_function>;
188
217
public:
189
218
using base::base;
219
+ constexpr explicit trivial_inplace_function (base && b) noexcept :
220
+ base(std::move(b))
221
+ {
222
+ }
190
223
using base::operator ();
191
224
};
192
225
193
226
} // namespace containers
194
227
195
- using empty_const_function = containers::trivial_inplace_function<int () const , 0 >;
196
- using const_function = containers::trivial_inplace_function<int () const , 24 >;
197
- using empty_mutable_function = containers::trivial_inplace_function<int (), 0 >;
198
- using mutable_function = containers::trivial_inplace_function<int (), 24 >;
199
-
200
- static_assert (std::is_trivially_copyable_v<empty_const_function>);
201
- static_assert (std::is_trivially_copyable_v<const_function>);
202
- static_assert (std::is_trivially_copyable_v<empty_mutable_function>);
203
- static_assert (std::is_trivially_copyable_v<mutable_function>);
204
-
205
- static_assert (std::invocable<empty_const_function const &>);
206
- static_assert (std::invocable<const_function const &>);
207
- static_assert (std::invocable<empty_const_function &>);
208
- static_assert (std::invocable<const_function &>);
209
-
210
- static_assert (!std::invocable<empty_mutable_function const &>);
211
- static_assert (!std::invocable<mutable_function const &>);
212
- static_assert (std::invocable<empty_mutable_function &>);
213
- static_assert (std::invocable<mutable_function &>);
214
-
215
- constexpr auto normal_function () -> int {
216
- return 2 ;
217
- }
218
- static_assert (empty_const_function(normal_function)() == 2 );
219
- static_assert (bounded::constructible_from<const_function, int (*)()>);
220
- static_assert (empty_mutable_function(normal_function)() == 2 );
221
- static_assert (bounded::constructible_from<const_function, int (*)()>);
222
-
223
- static_assert (!bounded::constructible_from<empty_const_function, void (*)()>);
224
- static_assert (!bounded::constructible_from<const_function, void (*)()>);
225
- static_assert (!bounded::constructible_from<empty_const_function, long (*)()>);
226
- static_assert (!bounded::constructible_from<const_function, long (*)()>);
227
-
228
- template <std::size_t size>
229
- struct sized_function {
230
- [[no_unique_address]] containers::array<std::byte, bounded::constant<size>> a;
231
- auto operator ()() const {
232
- return 1 ;
228
+ template <containers::function_signature Signature, std::size_t capacity, std::size_t alignment>
229
+ struct bounded ::tombstone_traits<containers::trivial_inplace_function<Signature, capacity, alignment>> {
230
+ private:
231
+ using T = containers::trivial_inplace_function<Signature, capacity, alignment>;
232
+ using base = tombstone_traits<typename T::base>;
233
+ public:
234
+ static constexpr auto spare_representations = base::spare_representations;
235
+
236
+ static constexpr auto make (bounded::constant_t <0 >) noexcept {
237
+ return T (base::make (0_bi));
238
+ }
239
+ static constexpr auto index (T const & value) noexcept {
240
+ return base::index (value);
233
241
}
234
242
};
235
-
236
- static_assert (bounded::constructible_from<empty_const_function, sized_function<0 >>);
237
- static_assert (bounded::constructible_from<const_function, sized_function<0 >>);
238
- static_assert (bounded::constructible_from<empty_mutable_function, sized_function<0 >>);
239
- static_assert (bounded::constructible_from<mutable_function, sized_function<0 >>);
240
-
241
- static_assert (!bounded::constructible_from<empty_const_function, sized_function<24 >>);
242
- static_assert (bounded::constructible_from<const_function, sized_function<24 >>);
243
- static_assert (!bounded::constructible_from<empty_mutable_function, sized_function<24 >>);
244
- static_assert (bounded::constructible_from<mutable_function, sized_function<24 >>);
245
-
246
- static_assert (!bounded::constructible_from<empty_const_function, sized_function<25 >>);
247
- static_assert (!bounded::constructible_from<const_function, sized_function<25 >>);
248
- static_assert (!bounded::constructible_from<empty_mutable_function, sized_function<25 >>);
249
- static_assert (!bounded::constructible_from<mutable_function, sized_function<25 >>);
250
-
251
- static_assert (sizeof (containers::trivial_inplace_function<void () const , 0 >) == sizeof (void (*)()));
252
-
253
- constexpr auto returns_five = empty_const_function([] { return 5 ; });
254
- static_assert (returns_five() == 5 );
255
-
256
- [[maybe_unused]] void test_lambdas () {
257
- constexpr auto empty_capture_lambda = [=]{};
258
- using empty_capture_lambda_t = decltype (empty_capture_lambda);
259
- static_assert (std::is_empty_v<empty_capture_lambda_t >);
260
- static_assert (!bounded::trivially_default_constructible<empty_capture_lambda_t >);
261
- static_assert (!bounded::constructible_from<empty_const_function, empty_capture_lambda_t >);
262
-
263
- constexpr auto non_empty_lambda = [x = 0 ]{ static_cast <void >(x); };
264
- using non_empty_lambda_t = decltype (non_empty_lambda);
265
- static_assert (!std::is_empty_v<non_empty_lambda_t >);
266
- static_assert (!bounded::constructible_from<empty_const_function, non_empty_lambda_t >);
267
- }
0 commit comments