From 4c4eb61c188347f6956dfcd075e190c79f0a970c Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Sun, 1 Sep 2019 13:03:01 +1000 Subject: [PATCH] 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. --- src/command_manager.cc | 5 ++--- src/command_manager.hh | 2 +- src/line_modification.cc | 2 +- src/line_modification.hh | 4 +--- src/utils.hh | 32 ++++++++++++++++++++++++++++++++ 5 files changed, 37 insertions(+), 8 deletions(-) diff --git a/src/command_manager.cc b/src/command_manager.cc index dcf862ae..294d3eab 100644 --- a/src/command_manager.cc +++ b/src/command_manager.cc @@ -462,10 +462,9 @@ String expand(StringView str, const Context& context, String expand(StringView str, const Context& context, const ShellContext& shell_context, - const std::function& postprocess) + const FunctionRef& postprocess) { - return expand_impl(str, context, shell_context, - [&](String s) { return postprocess(std::move(s)); }); + return expand_impl(str, context, shell_context, postprocess); } struct command_not_found : runtime_error diff --git a/src/command_manager.hh b/src/command_manager.hh index 774b8b2c..8a3a9f23 100644 --- a/src/command_manager.hh +++ b/src/command_manager.hh @@ -168,7 +168,7 @@ String expand(StringView str, const Context& context, String expand(StringView str, const Context& context, const ShellContext& shell_context, - const std::function& postprocess); + const FunctionRef& postprocess); } diff --git a/src/line_modification.cc b/src/line_modification.cc index d052cb54..01ad22bf 100644 --- a/src/line_modification.cc +++ b/src/line_modification.cc @@ -145,7 +145,7 @@ void LineRangeSet::update(ConstArrayView modifs) erase(std::remove_if(begin(), end(), [](auto& r) { return r.begin >= r.end; }), end()); } -void LineRangeSet::add_range(LineRange range, std::function on_new_range) +void LineRangeSet::add_range(LineRange range, FunctionRef on_new_range) { auto it = std::lower_bound(begin(), end(), range.begin, [](LineRange range, LineCount line) { return range.end < line; }); diff --git a/src/line_modification.hh b/src/line_modification.hh index 5cb4d350..b9c9cfcd 100644 --- a/src/line_modification.hh +++ b/src/line_modification.hh @@ -7,8 +7,6 @@ #include "range.hh" #include "vector.hh" -#include - namespace Kakoune { @@ -40,7 +38,7 @@ struct LineRangeSet : private Vector void reset(LineRange range) { Base::operator=({range}); } void update(ConstArrayView modifs); - void add_range(LineRange range, std::function on_new_range); + void add_range(LineRange range, FunctionRef on_new_range); void remove_range(LineRange range); }; 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>(value); } +template class FunctionRef; + +template +class FunctionRef +{ +public: + FunctionRef() + : m_target{nullptr}, + m_invoker{[](void* target, Args... args) { + if constexpr (!std::is_same_v) return Res{}; + }} + {} + + template + FunctionRef(Target&& target) + : m_target{&target}, + m_invoker{[](void* target, Args... args) { + return (*reinterpret_cast(target))(static_cast(args)...); + }} + {} + + Res operator()(Args... args) const + { + return m_invoker(m_target, static_cast(args)...); + } + +private: + using Invoker = Res (void*, Args...); + void* m_target; + Invoker* m_invoker; +}; + } #endif // utils_hh_INCLUDED