```c++ #pragma once #include #include #include #include namespace util { /// /// @brief Class storing a type-erased function object/pointer. /// @details This class does not employ dynamic memory allocation; instead, it /// stores the function object/pointer in a fixed-size buffer, the size of which /// can be specified as a template parameter. /// @warning This class does not take ownership of any resources it is /// constructed from. It is the responsibility of the user to ensure that the /// function object/pointer outlives the InplaceFunction object. /// /// @tparam func_sig_t Signature of the function. /// @tparam t_storage_size Size of the storage buffer, in bytes. /// template class InplaceFunction; template class InplaceFunction { using storage_t = char[storage_size]; using wrapper_func_t = return_t (*)(storage_t, args_t...); public: InplaceFunction() = default; /// /// @brief Constructor for function objects. /// template InplaceFunction(F f) { bind(f); } /// /// @brief Construct from free function pointer. /// template static InplaceFunction construct() { InplaceFunction func; func.template bind(); return func; } /// /// @brief Construct form member function pointer. /// template static InplaceFunction construct(class_t& c) { InplaceFunction func; func.template bind(c); return func; } /// /// @brief Construct from function object. /// template static InplaceFunction construct(F f) { InplaceFunction func; func.bind(f); return func; } /// /// @warning If no callable has been bound, calling this function will /// result in undefined behavior. /// return_t operator()(args_t... args) { return mWrapper(mStorage, args...); } operator bool() const { return !(mWrapper == nullptr); } /// /// @brief Bind a free function. /// /// @tparam F Pointer to free function /// template requires std::is_invocable_r_v void bind() { mWrapper = [](storage_t, args_t... args) { return F(std::forward(args)...); // return std::invoke(F, std::forward(args)...); }; } /// /// @brief Bind a member function. /// /// @tparam class_t Class the member belongs to. /// @param c Reference to object the member function should be called on. /// @tparam F Member function pointer. /// template requires std::is_invocable_r_v && (sizeof(class_t*) <= storage_size) void bind(class_t& c) { new (mStorage)(class_t*){&c}; mWrapper = [](storage_t storage, args_t... args) { return F(*reinterpret_cast(storage), std::forward(args)...); }; } /// /// @brief Bind a function object. /// template requires std::is_invocable_r_v && (sizeof(F) <= storage_size) && std::is_trivially_destructible_v void bind(F f) { new (mStorage) F{std::move(f)}; mWrapper = [](storage_t storage, args_t... args) { return (*reinterpret_cast(storage))( std::forward(args)...); }; } private: storage_t mStorage; wrapper_func_t mWrapper = nullptr; }; } // namespace util ```