| 
							- /*
 -   ==============================================================================
 - 
 -    This file is part of the JUCE library.
 -    Copyright (c) 2022 - Raw Material Software Limited
 - 
 -    JUCE is an open source library subject to commercial or open-source
 -    licensing.
 - 
 -    By using JUCE, you agree to the terms of both the JUCE 7 End-User License
 -    Agreement and JUCE Privacy Policy.
 - 
 -    End User License Agreement: www.juce.com/juce-7-licence
 -    Privacy Policy: www.juce.com/juce-privacy-policy
 - 
 -    Or: You may also use this code under the terms of the GPL v3 (see
 -    www.gnu.org/licenses).
 - 
 -    JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
 -    EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
 -    DISCLAIMED.
 - 
 -   ==============================================================================
 - */
 - 
 - namespace juce
 - {
 - namespace dsp
 - {
 - 
 - #ifndef DOXYGEN
 - 
 - namespace detail
 - {
 -     template <typename Ret, typename... Args>
 -     struct Vtable
 -     {
 -         using Storage = void*;
 - 
 -         using Move  = void (*) (Storage, Storage);
 -         using Call  = Ret  (*) (Storage, Args...);
 -         using Clear = void (*) (Storage);
 - 
 -         constexpr Vtable (Move moveIn, Call callIn, Clear clearIn) noexcept
 -                 : move (moveIn), call (callIn), clear (clearIn) {}
 - 
 -         Move  move  = nullptr;
 -         Call  call  = nullptr;
 -         Clear clear = nullptr;
 -     };
 - 
 -     template <typename Fn>
 -     void move (void* from, void* to)
 -     {
 -         new (to) Fn (std::move (*reinterpret_cast<Fn*> (from)));
 -     }
 - 
 -     template <typename Fn, typename Ret, typename... Args>
 -     typename std::enable_if<std::is_same<Ret, void>::value, Ret>::type call (void* s, Args... args)
 -     {
 -         (*reinterpret_cast<Fn*> (s)) (args...);
 -     }
 - 
 -     template <typename Fn, typename Ret, typename... Args>
 -     typename std::enable_if<! std::is_same<Ret, void>::value, Ret>::type call (void* s, Args... args)
 -     {
 -         return (*reinterpret_cast<Fn*> (s)) (std::forward<Args> (args)...);
 -     }
 - 
 -     template <typename Fn>
 -     void clear (void* s)
 -     {
 -         auto& fn = *reinterpret_cast<Fn*> (s);
 -         fn.~Fn();
 -         // I know this looks insane, for some reason MSVC 14 sometimes thinks fn is unreferenced
 -         ignoreUnused (fn);
 -     }
 - 
 -     template <typename Fn, typename Ret, typename... Args>
 -     constexpr Vtable<Ret, Args...> makeVtable()
 -     {
 -         return { move <Fn>, call <Fn, Ret, Args...>, clear<Fn> };
 -     }
 - } // namespace detail
 - 
 - template <size_t len, typename T>
 - class FixedSizeFunction;
 - 
 - #endif
 - 
 - /**
 -     A type similar to `std::function` that holds a callable object.
 - 
 -     Unlike `std::function`, the callable object will always be stored in
 -     a buffer of size `len` that is internal to the FixedSizeFunction instance.
 -     This in turn means that creating a FixedSizeFunction instance will never allocate,
 -     making FixedSizeFunctions suitable for use in realtime contexts.
 - 
 -     @tags{DSP}
 - */
 - template <size_t len, typename Ret, typename... Args>
 - class FixedSizeFunction<len, Ret (Args...)>
 - {
 - private:
 -     using Storage = typename std::aligned_storage<len>::type;
 - 
 -     template <typename Item>
 -     using Decay = typename std::decay<Item>::type;
 - 
 -     template <typename Item, typename Fn = Decay<Item>>
 -     using IntIfValidConversion = typename std::enable_if<sizeof (Fn) <= len
 -                                                              && alignof (Fn) <= alignof (Storage)
 -                                                              && ! std::is_same<FixedSizeFunction, Fn>::value,
 -                                                          int>::type;
 - 
 - public:
 -     /** Create an empty function. */
 -     FixedSizeFunction() noexcept = default;
 - 
 -     /** Create an empty function. */
 -     FixedSizeFunction (std::nullptr_t) noexcept
 -         : FixedSizeFunction() {}
 - 
 -     FixedSizeFunction (const FixedSizeFunction&) = delete;
 - 
 -     /** Forwards the passed Callable into the internal storage buffer. */
 -     template <typename Callable,
 -               typename Fn = Decay<Callable>,
 -               IntIfValidConversion<Callable> = 0>
 -     FixedSizeFunction (Callable&& callable)
 -     {
 -         static_assert (sizeof (Fn) <= len,
 -                        "The requested function cannot fit in this FixedSizeFunction");
 -         static_assert (alignof (Fn) <= alignof (Storage),
 -                        "FixedSizeFunction cannot accommodate the requested alignment requirements");
 - 
 -         static constexpr auto vtableForCallable = detail::makeVtable<Fn, Ret, Args...>();
 -         vtable = &vtableForCallable;
 - 
 -         auto* ptr = new (&storage) Fn (std::forward<Callable> (callable));
 -         jassertquiet ((void*) ptr == (void*) &storage);
 -     }
 - 
 -     /** Move constructor. */
 -     FixedSizeFunction (FixedSizeFunction&& other) noexcept
 -         : vtable (other.vtable)
 -     {
 -         move (std::move (other));
 -     }
 - 
 -     /** Converting constructor from smaller FixedSizeFunctions. */
 -     template <size_t otherLen, typename std::enable_if<(otherLen < len), int>::type = 0>
 -     FixedSizeFunction (FixedSizeFunction<otherLen, Ret (Args...)>&& other) noexcept
 -         : vtable (other.vtable)
 -     {
 -         move (std::move (other));
 -     }
 - 
 -     /** Nulls this instance. */
 -     FixedSizeFunction& operator= (std::nullptr_t) noexcept
 -     {
 -         return *this = FixedSizeFunction();
 -     }
 - 
 -     FixedSizeFunction& operator= (const FixedSizeFunction&) = delete;
 - 
 -     /** Assigns a new callable to this instance. */
 -     template <typename Callable, IntIfValidConversion<Callable> = 0>
 -     FixedSizeFunction& operator= (Callable&& callable)
 -     {
 -         return *this = FixedSizeFunction (std::forward<Callable> (callable));
 -     }
 - 
 -     /** Move assignment from smaller FixedSizeFunctions. */
 -     template <size_t otherLen, typename std::enable_if<(otherLen < len), int>::type = 0>
 -     FixedSizeFunction& operator= (FixedSizeFunction<otherLen, Ret (Args...)>&& other) noexcept
 -     {
 -         return *this = FixedSizeFunction (std::move (other));
 -     }
 - 
 -     /** Move assignment operator. */
 -     FixedSizeFunction& operator= (FixedSizeFunction&& other) noexcept
 -     {
 -         clear();
 -         vtable = other.vtable;
 -         move (std::move (other));
 -         return *this;
 -     }
 - 
 -     /** Destructor. */
 -     ~FixedSizeFunction() noexcept { clear(); }
 - 
 -     /** If this instance is currently storing a callable object, calls that object,
 -         otherwise throws `std::bad_function_call`.
 -     */
 -     Ret operator() (Args... args) const
 -     {
 -         if (vtable != nullptr)
 -             return vtable->call (&storage, std::forward<Args> (args)...);
 - 
 -         throw std::bad_function_call();
 -     }
 - 
 -     /** Returns true if this instance currently holds a callable. */
 -     explicit operator bool() const noexcept { return vtable != nullptr; }
 - 
 - private:
 -     template <size_t, typename>
 -     friend class FixedSizeFunction;
 - 
 -     void clear() noexcept
 -     {
 -         if (vtable != nullptr)
 -             vtable->clear (&storage);
 -     }
 - 
 -     template <size_t otherLen, typename T>
 -     void move (FixedSizeFunction<otherLen, T>&& other) noexcept
 -     {
 -         if (vtable != nullptr)
 -             vtable->move (&other.storage, &storage);
 -     }
 - 
 -     const detail::Vtable<Ret, Args...>* vtable = nullptr;
 -     mutable Storage storage;
 - };
 - 
 - template <size_t len, typename T>
 - bool operator!= (const FixedSizeFunction<len, T>& fn, std::nullptr_t) { return bool (fn); }
 - 
 - template <size_t len, typename T>
 - bool operator!= (std::nullptr_t, const FixedSizeFunction<len, T>& fn) { return bool (fn); }
 - 
 - template <size_t len, typename T>
 - bool operator== (const FixedSizeFunction<len, T>& fn, std::nullptr_t) { return ! (fn != nullptr); }
 - 
 - template <size_t len, typename T>
 - bool operator== (std::nullptr_t, const FixedSizeFunction<len, T>& fn) { return ! (fn != nullptr); }
 - 
 - 
 - }
 - }
 
 
  |