62 [[nodiscard]]
const char*
what() const noexcept
override {
63 return "aria::inplace_function: invoking an empty wrapper";
67namespace detail::inplace {
75enum class Op :
unsigned char {
82void manager_for(Op op,
void* self,
void* other) {
83 auto* dst =
static_cast<Fn*
>(self);
88 case Op::MoveConstruct: {
89 auto* src =
static_cast<Fn*
>(other);
90 ::new (dst) Fn(std::move(*src));
93 case Op::CopyConstruct: {
94 const auto* src =
static_cast<const Fn*
>(other);
104 std::size_t Capacity = 32,
105 std::size_t Alignment =
alignof(std::max_align_t)>
108template<
class R,
class... Args, std::size_t Capacity, std::size_t Alignment>
118 class Decayed = std::decay_t<Fn>,
119 class = std::enable_if_t<
120 !std::is_same_v<Decayed, inplace_function> &&
121 std::is_invocable_r_v<R, Decayed&, Args...> &&
122 std::is_copy_constructible_v<Decayed> &&
123 std::is_move_constructible_v<Decayed>>>
125 emplace_<Decayed>(std::forward<Fn>(fn));
133 if (
this != &other) {
145 if (
this != &other) {
158 class Decayed = std::decay_t<Fn>,
159 class = std::enable_if_t<
160 !std::is_same_v<Decayed, inplace_function> &&
161 std::is_invocable_r_v<R, Decayed&, Args...> &&
162 std::is_copy_constructible_v<Decayed> &&
163 std::is_move_constructible_v<Decayed>>>
166 emplace_<Decayed>(std::forward<Fn>(fn));
173 if (manager_ !=
nullptr) {
174 auto manager = std::exchange(manager_,
nullptr);
178 manager(detail::inplace::Op::Destroy, storage_(),
nullptr);
182 explicit operator bool() const noexcept {
return invoker_ !=
nullptr; }
185 if (invoker_ ==
nullptr) {
188 return invoker_(storage_(), std::forward<Args>(args)...);
200 if (invoker_ ==
nullptr)
return {};
212 return a.invoker_ ==
nullptr;
215 return a.invoker_ ==
nullptr;
218 return a.invoker_ !=
nullptr;
221 return a.invoker_ !=
nullptr;
225 using Invoker = R (*)(
const void*, Args...);
227 void (*)(detail::inplace::Op,
void* ,
void* );
229 template<
class Stored,
class U>
230 void emplace_(U&& fn) {
231 static_assert(
sizeof(Stored) <= Capacity,
232 "aria::inplace_function: callable does not fit. "
233 "Either reduce capture size or increase Capacity.");
234 static_assert(
alignof(Stored) <= Alignment,
235 "aria::inplace_function: callable alignment exceeds Alignment. "
236 "Increase the Alignment template parameter.");
239 using Argument = std::remove_reference_t<U>;
240 if constexpr (std::is_pointer_v<Argument> || std::is_member_pointer_v<Argument>) {
241 if (fn ==
nullptr)
return;
243 ::new (storage_()) Stored(
std::forward<U>(fn));
244 invoker_ = &invoke_<Stored>;
245 manager_ = &detail::inplace::manager_for<Stored>;
249 static R invoke_(const
void* obj, Args... args) {
253 auto* p =
const_cast<Fn*
>(
static_cast<const Fn*
>(obj));
254 if constexpr (std::is_void_v<R>) {
255 std::invoke(*p, std::forward<Args>(args)...);
257 return std::invoke(*p, std::forward<Args>(args)...);
261 void move_from_(inplace_function& other) {
262 if (other.manager_ !=
nullptr) {
263 other.manager_(detail::inplace::Op::MoveConstruct,
264 storage_(), other.storage_());
265 invoker_ = other.invoker_;
266 manager_ = other.manager_;
271 void copy_from_(
const inplace_function& other) {
272 if (other.manager_ !=
nullptr) {
276 other.manager_(detail::inplace::Op::CopyConstruct,
278 const_cast<void*
>(other.storage_()));
279 invoker_ = other.invoker_;
280 manager_ = other.manager_;
284 void* storage_() noexcept {
285 return static_cast<void*
>(&buffer_);
287 const void* storage_() const noexcept {
288 return static_cast<const void*
>(&buffer_);
291 alignas(Alignment) std::byte buffer_[Capacity]{};
292 Invoker invoker_ =
nullptr;
293 ManagerFn manager_ =
nullptr;
Definition inplace_function.hpp:60
const char * what() const noexcept override
Definition inplace_function.hpp:62
Definition function_ref.hpp:60
friend bool operator==(const inplace_function &a, std::nullptr_t) noexcept
Definition inplace_function.hpp:211
void reset() noexcept
Definition inplace_function.hpp:172
function_ref< R(Args...)> ref() const noexcept
Definition inplace_function.hpp:207
inplace_function & operator=(inplace_function &&other)
Definition inplace_function.hpp:144
inplace_function(inplace_function &&other)
Definition inplace_function.hpp:140
friend bool operator!=(const inplace_function &a, std::nullptr_t) noexcept
Definition inplace_function.hpp:217
constexpr inplace_function() noexcept=default
~inplace_function()
Definition inplace_function.hpp:170
friend bool operator==(std::nullptr_t, const inplace_function &a) noexcept
Definition inplace_function.hpp:214
inplace_function & operator=(std::nullptr_t) noexcept
Definition inplace_function.hpp:152
inplace_function(const inplace_function &other)
Definition inplace_function.hpp:128
R operator()(Args... args) const
Definition inplace_function.hpp:184
inplace_function & operator=(const inplace_function &other)
Definition inplace_function.hpp:132
friend bool operator!=(std::nullptr_t, const inplace_function &a) noexcept
Definition inplace_function.hpp:220
inplace_function(Fn &&fn)
Definition inplace_function.hpp:124
inplace_function & operator=(Fn &&fn)
Definition inplace_function.hpp:164
R result_type
Definition inplace_function.hpp:111
Definition inplace_function.hpp:106
Definition validation_key.hpp:110