diff options
| author | Maxime Coste <mawww@kakoune.org> | 2019-09-01 13:03:01 +1000 |
|---|---|---|
| committer | Maxime Coste <mawww@kakoune.org> | 2019-09-01 13:04:47 +1000 |
| commit | 4c4eb61c188347f6956dfcd075e190c79f0a970c (patch) | |
| tree | 4a39400d0dc21244066c77ab07d930848beeed04 /src/utils.hh | |
| parent | b24be99fa3e684201faed534c5988940d561df35 (diff) | |
Introduce FunctionRef to replace std::function when not storing
std::function is not necessary when we just want to pass a type
erased callback that does not need to own its target. FunctionRef
provides that functionality for a much lower compile time cost.
Diffstat (limited to 'src/utils.hh')
| -rw-r--r-- | src/utils.hh | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/src/utils.hh b/src/utils.hh index 9b6d87bb..f9c53509 100644 --- a/src/utils.hh +++ b/src/utils.hh @@ -154,6 +154,38 @@ auto to_underlying(E value) return static_cast<std::underlying_type_t<E>>(value); } +template<typename> class FunctionRef; + +template<typename Res, typename... Args> +class FunctionRef<Res(Args...)> +{ +public: + FunctionRef() + : m_target{nullptr}, + m_invoker{[](void* target, Args... args) { + if constexpr (!std::is_same_v<Res, void>) return Res{}; + }} + {} + + template<typename Target> + FunctionRef(Target&& target) + : m_target{&target}, + m_invoker{[](void* target, Args... args) { + return (*reinterpret_cast<Target*>(target))(static_cast<Args>(args)...); + }} + {} + + Res operator()(Args... args) const + { + return m_invoker(m_target, static_cast<Args>(args)...); + } + +private: + using Invoker = Res (void*, Args...); + void* m_target; + Invoker* m_invoker; +}; + } #endif // utils_hh_INCLUDED |
