1+ #pragma once
2+ #ifdef __AVR__
3+ #include < Arduino.h>
4+ extern void * operator new (size_t size, void * ptr);
5+ namespace nonstd {
6+
7+ template <class T >struct tag {using type=T;};
8+ template <class Tag >using type_t =typename Tag::type;
9+
10+ using size_t =decltype (sizeof (int ));
11+
12+ // move
13+
14+ template <class T >
15+ T&& move(T&t){return static_cast <T&&>(t);}
16+
17+ // forward
18+
19+ template <class T >
20+ struct remove_reference :tag<T>{};
21+ template <class T >
22+ struct remove_reference <T&>:tag<T>{};
23+ template <class T >using remove_reference_t =type_t <remove_reference<T>>;
24+
25+ template <class T >
26+ T&& forward( remove_reference_t <T>& t ) {
27+ return static_cast <T&&>(t);
28+ }
29+ template <class T >
30+ T&& forward( remove_reference_t <T>&& t ) {
31+ return static_cast <T&&>(t);
32+ }
33+
34+ // decay
35+
36+ template <class T >
37+ struct remove_const :tag<T>{};
38+ template <class T >
39+ struct remove_const <T const >:tag<T>{};
40+
41+ template <class T >
42+ struct remove_volatile :tag<T>{};
43+ template <class T >
44+ struct remove_volatile <T volatile >:tag<T>{};
45+
46+ template <class T >
47+ struct remove_cv :remove_const<type_t <remove_volatile<T>>>{};
48+
49+
50+ template <class T >
51+ struct decay3 :remove_cv<T>{};
52+ template <class R , class ...Args>
53+ struct decay3 <R(Args...)>:tag<R(*)(Args...)>{};
54+ template <class T >
55+ struct decay2 :decay3<T>{};
56+ template <class T , size_t N>
57+ struct decay2 <T[N]>:tag<T*>{};
58+
59+ template <class T >
60+ struct decay :decay2<remove_reference_t <T>>{};
61+
62+ template <class T >
63+ using decay_t =type_t <decay<T>>;
64+
65+ // is_convertible
66+
67+ template <class T >
68+ T declval (); // no implementation
69+
70+ template <class T , T t>
71+ struct integral_constant {
72+ static constexpr T value=t;
73+ constexpr integral_constant () {};
74+ constexpr operator T ()const { return value; }
75+ constexpr T operator ()()const { return value; }
76+ };
77+ template <bool b>
78+ using bool_t =integral_constant<bool , b>;
79+ using true_type=bool_t <true >;
80+ using false_type=bool_t <false >;
81+
82+ template <class ...>struct voider :tag<void >{};
83+ template <class ...Ts>using void_t =type_t <voider<Ts...>>;
84+
85+ namespace details {
86+ template <template <class ...>class Z , class , class ...Ts>
87+ struct can_apply :false_type{};
88+ template <template <class ...>class Z , class ...Ts>
89+ struct can_apply <Z, void_t <Z<Ts...>>, Ts...>:true_type{};
90+ }
91+ template <template <class ...>class Z , class ...Ts>
92+ using can_apply = details::can_apply<Z, void , Ts...>;
93+
94+ namespace details {
95+ template <class From , class To >
96+ using try_convert = decltype ( To{declval<From>()} );
97+ }
98+ template <class From , class To >
99+ struct is_convertible : can_apply< details::try_convert, From, To > {};
100+ template <>
101+ struct is_convertible <void ,void >:true_type{};
102+
103+ // enable_if
104+
105+ template <bool , class =void >
106+ struct enable_if {};
107+ template <class T >
108+ struct enable_if <true , T>:tag<T>{};
109+ template <bool b, class T =void >
110+ using enable_if_t =type_t <enable_if<b,T>>;
111+
112+ // res_of
113+
114+ namespace details {
115+ template <class G , class ...Args>
116+ using invoke_t = decltype ( declval<G>()(declval<Args>()...) );
117+
118+ template <class Sig ,class =void >
119+ struct res_of {};
120+ template <class G , class ...Args>
121+ struct res_of <G(Args...), void_t <invoke_t <G, Args...>>>:
122+ tag<invoke_t <G, Args...>>
123+ {};
124+ }
125+ template <class Sig >
126+ using res_of = details::res_of<Sig>;
127+ template <class Sig >
128+ using res_of_t =type_t <res_of<Sig>>;
129+
130+ // aligned_storage
131+
132+ template <size_t size, size_t align>
133+ struct alignas (align) aligned_storage_t {
134+ char buff[size];
135+ };
136+
137+ // is_same
138+
139+ template <class A , class B >
140+ struct is_same :false_type{};
141+ template <class A >
142+ struct is_same <A,A>:true_type{};
143+
144+ template <class Sig , size_t sz, size_t algn>
145+ struct small_task ;
146+
147+ template <class R , class ...Args, size_t sz, size_t algn>
148+ struct small_task <R(Args...), sz, algn>{
149+ struct vtable_t {
150+ void (*mover)(void * src, void * dest);
151+ void (*destroyer)(void *);
152+ R (*invoke)(void const * t, Args&&...args);
153+ template <class T >
154+ static vtable_t const * get () {
155+ static const vtable_t table = {
156+ [](void * src, void *dest) {
157+ new (dest) T (move (*static_cast <T*>(src)));
158+ },
159+ [](void * t){ static_cast <T*>(t)->~T (); },
160+ [](void const * t, Args&&...args )->R {
161+ return (*static_cast <T const *>(t))(forward<Args>(args)...);
162+ }
163+ };
164+ return &table;
165+ }
166+ };
167+ vtable_t const * table = nullptr ;
168+ aligned_storage_t <sz, algn> data;
169+ template <class F ,
170+ class dF =decay_t <F>,
171+ enable_if_t <!is_same<dF, small_task>{}>* = nullptr ,
172+ enable_if_t <is_convertible< res_of_t <dF&(Args...)>, R >{}>* = nullptr
173+ >
174+ small_task ( F&& f ):
175+ table ( vtable_t ::template get<dF>() )
176+ {
177+ static_assert ( sizeof (dF) <= sz, " object too large" );
178+ static_assert ( alignof (dF) <= algn, " object too aligned" );
179+ new (&data) dF (forward<F>(f));
180+ }
181+ ~small_task () {
182+ if (table)
183+ table->destroyer (&data);
184+ }
185+ small_task (const small_task& o):
186+ table (o.table)
187+ {
188+ data = o.data ;
189+ }
190+ small_task (small_task&& o):
191+ table (o.table)
192+ {
193+ if (table)
194+ table->mover (&o.data , &data);
195+ }
196+ small_task (){}
197+ small_task& operator =(const small_task& o){
198+ this ->~small_task ();
199+ new (this ) small_task ( move (o) );
200+ return *this ;
201+ }
202+ small_task& operator =(small_task&& o){
203+ this ->~small_task ();
204+ new (this ) small_task ( move (o) );
205+ return *this ;
206+ }
207+ explicit operator bool ()const {return table;}
208+ R operator ()(Args...args)const {
209+ return table->invoke (&data, forward<Args>(args)...);
210+ }
211+ };
212+
213+ template <class R , class ...Args, size_t sz, size_t algn>
214+ inline bool operator ==(const small_task<R(Args...), sz, algn>& __f, nullptr_t )
215+ { return !static_cast <bool >(__f); }
216+
217+ // / @overload
218+ template <class R , class ...Args, size_t sz, size_t algn>
219+ inline bool operator ==(nullptr_t , const small_task<R(Args...), sz, algn>& __f)
220+ { return !static_cast <bool >(__f); }
221+
222+ template <class R , class ...Args, size_t sz, size_t algn>
223+ inline bool operator !=(const small_task<R(Args...), sz, algn>& __f, nullptr_t )
224+ { return static_cast <bool >(__f); }
225+
226+ // / @overload
227+ template <class R , class ...Args, size_t sz, size_t algn>
228+ inline bool operator !=(nullptr_t , const small_task<R(Args...), sz, algn>& __f)
229+ { return static_cast <bool >(__f); }
230+
231+ template <class Sig >
232+ using function = small_task<Sig, sizeof (void *)*4 , alignof (void *) >;
233+ }
234+
235+ #endif
0 commit comments