summaryrefslogtreecommitdiff
path: root/src/utils.hh
diff options
context:
space:
mode:
authorMaxime Coste <mawww@kakoune.org>2019-09-01 13:03:01 +1000
committerMaxime Coste <mawww@kakoune.org>2019-09-01 13:04:47 +1000
commit4c4eb61c188347f6956dfcd075e190c79f0a970c (patch)
tree4a39400d0dc21244066c77ab07d930848beeed04 /src/utils.hh
parentb24be99fa3e684201faed534c5988940d561df35 (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.hh32
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