diff --git a/firmware/controllers/system/timer/scheduler.h b/firmware/controllers/system/timer/scheduler.h index 08c184b4ea..71150cf9d0 100644 --- a/firmware/controllers/system/timer/scheduler.h +++ b/firmware/controllers/system/timer/scheduler.h @@ -8,6 +8,24 @@ typedef void (*schfunc_t)(void *); +template +std::enable_if_t< + sizeof(To) == sizeof(From) && + std::is_trivially_copyable_v && + std::is_trivially_copyable_v, + To> +// constexpr support needs compiler magic +bit_cast(const From& src) noexcept +{ + static_assert(std::is_trivially_constructible_v, + "This implementation additionally requires " + "destination type to be trivially constructible"); + + To dst; + std::memcpy(&dst, &src, sizeof(To)); + return dst; +} + class action_s { public: // Default constructor constructs null action (ie, implicit bool conversion returns false) @@ -16,13 +34,13 @@ public: // Allow implicit conversion from schfunc_t to action_s action_s(schfunc_t callback) : action_s(callback, nullptr) { } action_s(schfunc_t callback, void *param) : m_callback(callback), m_param(param) { } - template - action_s(schfunc_t callback, TParam& param) : m_callback(callback), m_param(¶m) { } // Allow any function that takes a single pointer parameter, so long as param is also of the same pointer type. // This constructor means you shouldn't ever have to cast to schfunc_t on your own. template action_s(void (*callback)(TArg*), TArg* param) : m_callback((schfunc_t)callback), m_param(param) { } + template + action_s(void (*callback)(TArg), TArg param) : m_callback(bit_cast(callback)), m_param(reinterpret_cast(param)) { } void execute(); schfunc_t getCallback() const;