54#if defined __ATTINY__ || defined(__ARDUINO__) || defined(__ARM__) || defined(__RISC_V__)
60using nullptr_t =
decltype(
nullptr);
64#if !defined(NEW_H) && !defined(USTD_FEATURE_SUPPORTS_NEW_OPERATOR)
65inline void *
operator new(
size_t size,
void *ptr) {
72template <
class T>
struct tag {
using type = T; };
73template <
class Tag>
using type_t =
typename Tag::type;
79template <
class T> T &&move(T &t) {
80 return static_cast<T &&
>(t);
85template <
class T>
struct remove_reference : tag<T> {};
86template <
class T>
struct remove_reference<T &> : tag<T> {};
87template <
class T>
using remove_reference_t = type_t<remove_reference<T>>;
89template <
class T> T &&forward(remove_reference_t<T> &t) {
90 return static_cast<T &&
>(t);
92template <
class T> T &&forward(remove_reference_t<T> &&t) {
93 return static_cast<T &&
>(t);
98template <
class T>
struct remove_const : tag<T> {};
99template <
class T>
struct remove_const<T const> : tag<T> {};
101template <
class T>
struct remove_volatile : tag<T> {};
102template <
class T>
struct remove_volatile<T volatile> : tag<T> {};
104template <
class T>
struct remove_cv : remove_const<type_t<remove_volatile<T>>> {};
106template <
class T>
struct decay3 : remove_cv<T> {};
107template <
class R,
class... Args>
struct decay3<R(Args...)> : tag<R (*)(Args...)> {};
108template <
class T>
struct decay2 : decay3<T> {};
109template <
class T,
size_t N>
struct decay2<T[N]> : tag<T *> {};
111template <
class T>
struct decay : decay2<remove_reference_t<T>> {};
113template <
class T>
using decay_t = type_t<decay<T>>;
117template <
class T> T declval();
119template <
class T, T t>
struct integral_constant {
120 static constexpr T value = t;
121 constexpr integral_constant(){};
122 constexpr operator T()
const {
125 constexpr T operator()()
const {
129template <
bool b>
using bool_t = integral_constant<bool, b>;
130using true_type = bool_t<true>;
131using false_type = bool_t<false>;
133template <
class...>
struct voider : tag<void> {};
134template <
class... Ts>
using void_t = type_t<voider<Ts...>>;
137template <
template <
class...>
class Z,
class,
class... Ts>
struct can_apply : false_type {};
138template <
template <
class...>
class Z,
class... Ts>
139struct can_apply<Z, void_t<Z<Ts...>>, Ts...> : true_type {};
141template <
template <
class...>
class Z,
class... Ts>
142using can_apply = details::can_apply<Z, void, Ts...>;
145template <
class From,
class To>
using try_convert =
decltype(To{declval<From>()});
147template <
class From,
class To>
148struct is_convertible : can_apply<details::try_convert, From, To> {};
149template <>
struct is_convertible<void, void> : true_type {};
153template <
bool,
class =
void>
struct enable_if {};
154template <
class T>
struct enable_if<true, T> : tag<T> {};
155template <
bool b,
class T =
void>
using enable_if_t = type_t<enable_if<b, T>>;
160template <
class G,
class... Args>
using invoke_t =
decltype(declval<G>()(declval<Args>()...));
162template <
class Sig,
class =
void>
struct res_of {};
163template <
class G,
class... Args>
164struct res_of<G(Args...), void_t<invoke_t<G, Args...>>> : tag<invoke_t<G, Args...>> {};
166template <
class Sig>
using res_of = details::res_of<Sig>;
167template <
class Sig>
using res_of_t = type_t<res_of<Sig>>;
171template <
size_t size,
size_t align>
struct alignas(align) aligned_storage_t {
char buff[size]; };
175template <
class A,
class B>
struct is_same : false_type {};
176template <
class A>
struct is_same<A, A> : true_type {};
178template <
class Sig,
size_t sz,
size_t algn>
struct small_task;
180template <
class R,
class... Args,
size_t sz,
size_t algn>
struct small_task<R(Args...), sz, algn> {
182 void (*mover)(
void *src,
void *dest);
183 void (*destroyer)(
void *);
184 R (*invoke)(
void const *t, Args &&...args);
185 template <
class T>
static vtable_t
const *get() {
186 static const vtable_t table = {
187 [](
void *src,
void *dest) {
new (dest) T(move(*
static_cast<T *
>(src))); },
188 [](
void *t) {
static_cast<T *
>(t)->~T(); },
189 [](
void const *t, Args &&...args) -> R {
190 return (*
static_cast<T
const *
>(t))(forward<Args>(args)...);
195 vtable_t
const *table =
nullptr;
196 aligned_storage_t<sz, algn> data;
197 template <
class F,
class dF = decay_t<F>, enable_if_t<!is_same<dF, small_task>{}> * =
nullptr,
198 enable_if_t<is_convertible<res_of_t<dF &(Args...)>, R>{}> * =
nullptr>
199 small_task(F &&f) : table(vtable_t::template get<dF>()) {
200 static_assert(
sizeof(dF) <= sz,
"object too large");
201 static_assert(
alignof(dF) <= algn,
"object too aligned");
202 new (&data) dF(forward<F>(f));
206 table->destroyer(&data);
208 small_task(
const small_task &o) : table(o.table) {
211 small_task(small_task &&o) : table(o.table) {
213 table->mover(&o.data, &data);
217 small_task &operator=(
const small_task &o) {
219 new (
this) small_task(move(o));
222 small_task &operator=(small_task &&o) {
224 new (
this) small_task(move(o));
227 explicit operator bool()
const {
230 R operator()(Args... args)
const {
231 return table->invoke(&data, forward<Args>(args)...);
235template <
class R,
class... Args,
size_t sz,
size_t algn>
236inline bool operator==(
const small_task<R(Args...), sz, algn> &__f, nullptr_t) {
237 return !
static_cast<bool>(__f);
241template <
class R,
class... Args,
size_t sz,
size_t algn>
242inline bool operator==(nullptr_t,
const small_task<R(Args...), sz, algn> &__f) {
243 return !
static_cast<bool>(__f);
246template <
class R,
class... Args,
size_t sz,
size_t algn>
247inline bool operator!=(
const small_task<R(Args...), sz, algn> &__f, nullptr_t) {
248 return static_cast<bool>(__f);
252template <
class R,
class... Args,
size_t sz,
size_t algn>
253inline bool operator!=(nullptr_t,
const small_task<R(Args...), sz, algn> &__f) {
254 return static_cast<bool>(__f);
257template <
class Sig>
using function = small_task<Sig,
sizeof(
void *) * 4,
alignof(
void *)>;
The ustd namespace.
Definition: ustd_array.h:34