1313// (which shouldn't happen, since the point of this is to avoid the heap,
1414// but it could...)
1515
16- template <unsigned BUFFER_SIZE = 2 * sizeof (void *)>
17- class CallbackSized {
18- private:
19- // static constexpr unsigned BUFFER_SIZE = 2 * sizeof(void *);
20-
21- public:
22- CallbackSized () = default ;
23-
24- template <typename Callable>
25- CallbackSized (Callable callable) {
26- static_assert (sizeof (Callable) <= BUFFER_SIZE);
27- static_assert (std::is_invocable_v<Callable>);
28-
29- new (&m_data[0 ]) Callable (callable);
30- m_callback = invoke<Callable>;
31- m_destroy = destroy<Callable>;
32- }
33-
34- ~CallbackSized () {
35- if (m_destroy)
36- m_destroy (&m_data[0 ]);
37- }
38-
39- void call () {
40- // if (m_callback)
41- m_callback (&m_data[0 ]);
42- return ;
43- }
44-
45- void operator ()() {
46- call ();
47- }
48-
49- operator bool () {
50- return m_callback;
51- }
52-
53- private:
54- template <typename Callable>
55- static void invoke (void *object) {
56- Callable &callable = *reinterpret_cast <Callable *>(object);
57- callable ();
58- }
59-
60- template <typename Callable>
61- static void destroy (void *object) {
62- Callable &callable = *reinterpret_cast <Callable *>(object);
63- callable.~Callable ();
64- }
65-
66- private:
67- using CallbackM = void (*)(void *);
68- CallbackM m_callback{};
69-
70- using Deleter = void (*)(void *);
71- Deleter m_destroy{};
72-
73- alignas (uint64_t ) uint8_t m_data[BUFFER_SIZE];
74- };
75-
76- using Callback = CallbackSized<2 * sizeof (void *)>;
77-
7816// Function<T> is a callback that takes parameters and returns something
79- template <typename Signature>
80- struct Function {};
81-
82- template <typename Ret, typename ... Args>
83- class Function <Ret(Args...)> {
84- private:
85- static constexpr uint8_t BUFFER_SIZE = 2 * sizeof (void *);
17+ template <unsigned buffer_size, typename Signature>
18+ struct FunctionSized {};
8619
20+ template <unsigned buffer_size, typename Ret, typename ... Args>
21+ class FunctionSized <buffer_size, Ret(Args...)> {
8722public:
88- Function () = default ;
23+ FunctionSized () = default ;
8924
9025 template <typename Callable>
91- Function ( Callable callable) {
92- static_assert ( sizeof ( Callable) <= BUFFER_SIZE);
93- static_assert (std::is_invocable_v <Callable, Args...>);
94-
26+ requires ( sizeof ( Callable) <= buffer_size && std::is_invocable_v<Callable, Args...>)
27+ FunctionSized ( Callable callable)
28+ : m_callback{invoke <Callable>}
29+ , m_destroy{destroy<Callable>} {
9530 new (&m_data[0 ]) Callable (callable);
96- m_callback = invoke<Callable>;
97- m_destroy = destroy<Callable>;
9831 }
9932
100- ~Function () {
33+ ~FunctionSized () {
10134 if (m_destroy)
10235 m_destroy (&m_data[0 ]);
10336 }
10437
10538 Ret call (Args... args) {
106- if (m_callback)
107- return m_callback (&m_data[0 ], std::forward<Args>(args)...);
108- return Ret ();
39+ return m_callback (&m_data[0 ], std::forward<Args>(args)...);
10940 }
11041
11142 Ret operator ()(Args... args) {
11243 return call (std::forward<Args>(args)...);
11344 }
11445
46+ operator bool () const {
47+ return m_callback;
48+ }
49+
11550private:
11651 template <typename Callable>
11752 static Ret invoke (void *object, Args... args) {
@@ -132,5 +67,13 @@ private:
13267 using Deleter = void (*)(void *);
13368 Deleter m_destroy{};
13469
135- alignas (uint64_t ) uint8_t m_data[BUFFER_SIZE ];
70+ alignas (uint64_t ) uint8_t m_data[buffer_size ];
13671};
72+
73+ template <typename Signature>
74+ using Function = FunctionSized<sizeof (void *) * 2 , Signature>;
75+
76+ template <unsigned size = sizeof (void *) * 2 >
77+ using CallbackSized = FunctionSized<size, void (void )>;
78+
79+ using Callback = CallbackSized<2 * sizeof (void *)>;
0 commit comments