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.
This commit is contained in:
Maxime Coste 2019-09-01 13:03:01 +10:00
parent b24be99fa3
commit 4c4eb61c18
5 changed files with 37 additions and 8 deletions

View File

@ -462,10 +462,9 @@ String expand(StringView str, const Context& context,
String expand(StringView str, const Context& context, String expand(StringView str, const Context& context,
const ShellContext& shell_context, const ShellContext& shell_context,
const std::function<String (String)>& postprocess) const FunctionRef<String (String)>& postprocess)
{ {
return expand_impl(str, context, shell_context, return expand_impl(str, context, shell_context, postprocess);
[&](String s) { return postprocess(std::move(s)); });
} }
struct command_not_found : runtime_error struct command_not_found : runtime_error

View File

@ -168,7 +168,7 @@ String expand(StringView str, const Context& context,
String expand(StringView str, const Context& context, String expand(StringView str, const Context& context,
const ShellContext& shell_context, const ShellContext& shell_context,
const std::function<String (String)>& postprocess); const FunctionRef<String (String)>& postprocess);
} }

View File

@ -145,7 +145,7 @@ void LineRangeSet::update(ConstArrayView<LineModification> modifs)
erase(std::remove_if(begin(), end(), [](auto& r) { return r.begin >= r.end; }), end()); erase(std::remove_if(begin(), end(), [](auto& r) { return r.begin >= r.end; }), end());
} }
void LineRangeSet::add_range(LineRange range, std::function<void (LineRange)> on_new_range) void LineRangeSet::add_range(LineRange range, FunctionRef<void (LineRange)> on_new_range)
{ {
auto it = std::lower_bound(begin(), end(), range.begin, auto it = std::lower_bound(begin(), end(), range.begin,
[](LineRange range, LineCount line) { return range.end < line; }); [](LineRange range, LineCount line) { return range.end < line; });

View File

@ -7,8 +7,6 @@
#include "range.hh" #include "range.hh"
#include "vector.hh" #include "vector.hh"
#include <functional>
namespace Kakoune namespace Kakoune
{ {
@ -40,7 +38,7 @@ struct LineRangeSet : private Vector<LineRange, MemoryDomain::Highlight>
void reset(LineRange range) { Base::operator=({range}); } void reset(LineRange range) { Base::operator=({range}); }
void update(ConstArrayView<LineModification> modifs); void update(ConstArrayView<LineModification> modifs);
void add_range(LineRange range, std::function<void (LineRange)> on_new_range); void add_range(LineRange range, FunctionRef<void (LineRange)> on_new_range);
void remove_range(LineRange range); void remove_range(LineRange range);
}; };

View File

@ -154,6 +154,38 @@ auto to_underlying(E value)
return static_cast<std::underlying_type_t<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 #endif // utils_hh_INCLUDED