JUCE-7.0.12-0-g4f43011b96 JUCE-7.0.12-0-g4f43011b96
JUCE — C++ application framework with suport for VST, VST3, LV2 audio plug-ins

« « « Anklang Documentation
Loading...
Searching...
No Matches
juce_FixedSizeFunction.h
Go to the documentation of this file.
1 /*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 The code included in this file is provided under the terms of the ISC license
11 http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12 To use, copy, modify, and/or distribute this software for any purpose with or
13 without fee is hereby granted provided that the above copyright notice and
14 this permission notice appear in all copies.
15
16 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18 DISCLAIMED.
19
20 ==============================================================================
21*/
22
23namespace juce
24{
25
26#ifndef DOXYGEN
27
28namespace detail
29{
30 template <typename Ret, typename... Args>
31 struct Vtable
32 {
33 using Storage = void*;
34
35 using Move = void (*) (Storage, Storage);
36 using Call = Ret (*) (Storage, Args...);
37 using Clear = void (*) (Storage);
38
39 constexpr Vtable (Move moveIn, Call callIn, Clear clearIn) noexcept
40 : move (moveIn), call (callIn), clear (clearIn) {}
41
42 Move move = nullptr;
43 Call call = nullptr;
44 Clear clear = nullptr;
45 };
46
47 template <typename Fn>
48 void move (void* from, void* to)
49 {
50 new (to) Fn (std::move (*reinterpret_cast<Fn*> (from)));
51 }
52
53 template <typename Fn, typename Ret, typename... Args>
54 std::enable_if_t<std::is_same_v<Ret, void>, Ret> call (void* s, Args... args)
55 {
56 (*reinterpret_cast<Fn*> (s)) (std::forward<Args> (args)...);
57 }
58
59 template <typename Fn, typename Ret, typename... Args>
60 std::enable_if_t<! std::is_same_v<Ret, void>, Ret> call (void* s, Args... args)
61 {
62 return (*reinterpret_cast<Fn*> (s)) (std::forward<Args> (args)...);
63 }
64
65 template <typename Fn>
66 void clear (void* s)
67 {
68 // I know this looks insane, for some reason MSVC 14 sometimes thinks fn is unreferenced
69 [[maybe_unused]] auto& fn = *reinterpret_cast<Fn*> (s);
70 fn.~Fn();
71 }
72
73 template <typename Fn, typename Ret, typename... Args>
74 constexpr Vtable<Ret, Args...> makeVtable()
75 {
76 return { move <Fn>, call <Fn, Ret, Args...>, clear<Fn> };
77 }
78} // namespace detail
79
80template <size_t len, typename T>
81class FixedSizeFunction;
82
83#endif
84
95template <size_t len, typename Ret, typename... Args>
96class FixedSizeFunction<len, Ret (Args...)>
97{
98private:
99 struct Storage { alignas (std::max_align_t) std::byte data[len]; };
100
101 template <typename Item>
103
104 template <typename Item, typename Fn = Decay<Item>>
105 using IntIfValidConversion = std::enable_if_t<sizeof (Fn) <= len
106 && alignof (Fn) <= alignof (Storage)
107 && ! std::is_same_v<FixedSizeFunction, Fn>,
108 int>;
109
110public:
112 FixedSizeFunction() noexcept = default;
113
115 FixedSizeFunction (std::nullptr_t) noexcept
116 : FixedSizeFunction() {}
117
118 FixedSizeFunction (const FixedSizeFunction&) = delete;
119
121 template <typename Callable,
122 typename Fn = Decay<Callable>,
123 IntIfValidConversion<Callable> = 0>
124 FixedSizeFunction (Callable&& callable)
125 {
126 static_assert (sizeof (Fn) <= len,
127 "The requested function cannot fit in this FixedSizeFunction");
128 static_assert (alignof (Fn) <= alignof (Storage),
129 "FixedSizeFunction cannot accommodate the requested alignment requirements");
130
131 static constexpr auto vtableForCallable = detail::makeVtable<Fn, Ret, Args...>();
132 vtable = &vtableForCallable;
133
134 [[maybe_unused]] auto* ptr = new (&storage) Fn (std::forward<Callable> (callable));
135 jassert ((void*) ptr == (void*) &storage);
136 }
137
139 FixedSizeFunction (FixedSizeFunction&& other) noexcept
140 : vtable (other.vtable)
141 {
142 move (std::move (other));
143 }
144
146 template <size_t otherLen, std::enable_if_t<(otherLen < len), int> = 0>
147 FixedSizeFunction (FixedSizeFunction<otherLen, Ret (Args...)>&& other) noexcept
148 : vtable (other.vtable)
149 {
150 move (std::move (other));
151 }
152
154 FixedSizeFunction& operator= (std::nullptr_t) noexcept
155 {
156 return *this = FixedSizeFunction();
157 }
158
159 FixedSizeFunction& operator= (const FixedSizeFunction&) = delete;
160
162 template <typename Callable, IntIfValidConversion<Callable> = 0>
163 FixedSizeFunction& operator= (Callable&& callable)
164 {
165 return *this = FixedSizeFunction (std::forward<Callable> (callable));
166 }
167
169 template <size_t otherLen, std::enable_if_t<(otherLen < len), int> = 0>
170 FixedSizeFunction& operator= (FixedSizeFunction<otherLen, Ret (Args...)>&& other) noexcept
171 {
172 return *this = FixedSizeFunction (std::move (other));
173 }
174
176 FixedSizeFunction& operator= (FixedSizeFunction&& other) noexcept
177 {
178 clear();
179 vtable = other.vtable;
180 move (std::move (other));
181 return *this;
182 }
183
185 ~FixedSizeFunction() noexcept { clear(); }
186
190 Ret operator() (Args... args) const
191 {
192 if (vtable != nullptr)
193 return vtable->call (&storage, std::forward<Args> (args)...);
194
196 }
197
199 explicit operator bool() const noexcept { return vtable != nullptr; }
200
201private:
202 template <size_t, typename>
203 friend class FixedSizeFunction;
204
205 void clear() noexcept
206 {
207 if (vtable != nullptr)
208 vtable->clear (&storage);
209 }
210
211 template <size_t otherLen, typename T>
212 void move (FixedSizeFunction<otherLen, T>&& other) noexcept
213 {
214 if (vtable != nullptr)
215 vtable->move (&other.storage, &storage);
216 }
217
218 const detail::Vtable<Ret, Args...>* vtable = nullptr;
219 mutable Storage storage;
220};
221
222template <size_t len, typename T>
223bool operator!= (const FixedSizeFunction<len, T>& fn, std::nullptr_t) { return bool (fn); }
224
225template <size_t len, typename T>
226bool operator!= (std::nullptr_t, const FixedSizeFunction<len, T>& fn) { return bool (fn); }
227
228template <size_t len, typename T>
229bool operator== (const FixedSizeFunction<len, T>& fn, std::nullptr_t) { return ! (fn != nullptr); }
230
231template <size_t len, typename T>
232bool operator== (std::nullptr_t, const FixedSizeFunction<len, T>& fn) { return ! (fn != nullptr); }
233
234} // namespace juce
FixedSizeFunction() noexcept=default
Create an empty function.
FixedSizeFunction(FixedSizeFunction &&other) noexcept
Move constructor.
FixedSizeFunction(Callable &&callable)
Forwards the passed Callable into the internal storage buffer.
#define jassert(expression)
Platform-independent assertion macro.
T move(T... args)
JUCE Namespace.
Type unalignedPointerCast(void *ptr) noexcept
Casts a pointer to another type via void*, which suppresses the cast-align warning which sometimes ar...
Definition juce_Memory.h:88