14#ifndef OPENVPN_COMMON_FUNCTION_H
15#define OPENVPN_COMMON_FUNCTION_H
26template <
typename F, std::
size_t N = 3,
bool INTERN_ONLY = false>
29template <
typename R,
typename... A, std::size_t N,
bool INTERN_ONLY>
41 construct(std::move(functor));
46 methods = other.methods;
47 other.methods =
nullptr;
49 methods->move(data, other.data);
55 methods->destruct(data);
56 methods = other.methods;
57 other.methods =
nullptr;
59 methods->move(data, other.data);
66 methods->destruct(data);
70 void reset(T &&functor)
noexcept
73 methods->destruct(data);
74 construct(std::move(functor));
81 methods->destruct(data);
88 return methods->invoke(data, std::forward<A>(args)...);
91 explicit operator bool() const noexcept
93 return methods !=
nullptr;
99 void construct(T &&functor)
noexcept
101 constexpr bool is_intern = (
sizeof(Intern<T>) <=
sizeof(data));
102 static_assert(!INTERN_ONLY || is_intern,
"Function: Intern<T> doesn't fit in data[] and INTERN_ONLY=true");
103 static_assert(
sizeof(Extern<T>) <=
sizeof(data),
"Function: Extern<T> doesn't fit in data[]");
108 setup_methods_intern<T>();
109 new (data) Intern<T>(std::move(functor));
114 setup_methods_extern<T>();
115 new (data) Extern<T>(std::move(functor));
119 template <
typename T>
122 return sizeof(Intern<T>) <=
sizeof(data);
125 template <
typename T,
126 typename std::enable_if<is_intern<T>(),
int>::type = 0>
130 setup_methods_intern<T>();
131 new (data) Intern<T>(std::move(functor));
134 template <
typename T,
135 typename std::enable_if<!is_intern<T>(),
int>::type = 0>
138 static_assert(!INTERN_ONLY,
"Function: Intern<T> doesn't fit in data[] and INTERN_ONLY=true");
139 static_assert(
sizeof(Extern<T>) <=
sizeof(data),
"Function: Extern<T> doesn't fit in data[]");
142 setup_methods_extern<T>();
143 new (data) Extern<T>(std::move(functor));
149 R (*invoke)(
void *, A &&...);
150 void (*move)(
void *,
void *);
151 void (*destruct)(
void *);
154 template <
typename T>
157 static const struct Methods m = {
160 &Intern<T>::destruct,
165 template <
typename T>
168 static const struct Methods m = {
171 &Extern<T>::destruct,
177 template <
typename T>
182 : functor_(std::move(functor))
188 Intern *self =
reinterpret_cast<Intern *
>(ptr);
189 return self->functor_(std::forward<A>(args)...);
192 static void move(
void *dest,
void *src)
194 Intern *s =
reinterpret_cast<Intern *
>(src);
195 new (dest) Intern(std::move(*s));
200 Intern *self =
reinterpret_cast<Intern *
>(ptr);
209 template <
typename T>
214 : functor_(
new T(std::move(functor)))
220 Extern *self =
reinterpret_cast<Extern *
>(ptr);
221 return (*self->functor_)(std::forward<A>(args)...);
224 static void move(
void *dest,
void *src)
226 Extern *d =
reinterpret_cast<Extern *
>(dest);
227 Extern *s =
reinterpret_cast<Extern *
>(src);
228 d->functor_ = s->functor_;
234 Extern *self =
reinterpret_cast<Extern *
>(ptr);
235 delete self->functor_;
243 mutable void *data[N];
static void move(void *dest, void *src)
static R invoke(void *ptr, A &&...args)
static void destruct(void *ptr)
Extern(T &&functor) noexcept
static void move(void *dest, void *src)
static R invoke(void *ptr, A &&...args)
Intern(T &&functor) noexcept
static void destruct(void *ptr)
Function(Function &&other) noexcept
void setup_methods_extern()
R operator()(A... args) const
void setup_methods_intern()
Function(T &&functor) noexcept
static constexpr bool is_intern()
void construct(T &&functor) noexcept
Function & operator=(Function &&other) noexcept
void reset(T &&functor) noexcept