Reputation: 10982
Is it somehow possible to easily mimic std::bind_front
in C++17 ? (just for member function wrapping is fine)
I took a look at implementation in c++20 aiming to copy but it seems its very much implementation specific indeed.
I'm thinking a lambda wrapper or template function/object might work?
(Performance is not an issue here)
Upvotes: 1
Views: 1143
Reputation: 308
template<typename F, typename... FRONT_ARGS>
auto bind_front(F&& f, FRONT_ARGS&&... front_args)
{
// front_args are copied because multiple invocations of this closure are possible
return [captured_f = std::forward<F>(f), front_args...](auto&&... back_args) {
return std::invoke(captured_f, front_args...,
std::forward<decltype(back_args)>(back_args)...);
};
}
Upvotes: 0
Reputation: 37927
This can be a starting point
template<typename F, typename ...FrontArgs>
struct bindfronthelper
{
bindfronthelper(F f, FrontArgs&&...args)
: mF{std::move(f)}
, mFrontArg{std::forward<FrontArgs>(args)...}
{}
template<typename ...BackArgs>
auto operator()(BackArgs&&...args) const
{
return std::apply(mF, std::tuple_cat(mFrontArg, std::forward_as_tuple(args...)));
}
F mF;
std::tuple<std::decay_t<FrontArgs>...> mFrontArg;
};
template<typename F, typename ...FrontArgs>
auto mybindfront(F f, FrontArgs&&...args)
{
return bindfronthelper<F, FrontArgs...>{std::move(f), std::forward<FrontArgs>(args)...};
}
Written quickly and not tested well, so there might be some pitfalls in corner cases. At least it shows how this can be achieved.
Ok I made this over complicated, here is simpler version:
template<typename T, typename ...Args>
auto tuple_append(T&& t, Args&&...args)
{
return std::tuple_cat(
std::forward<T>(t),
std::forward_as_tuple(args...)
);
}
template<typename F, typename ...FrontArgs>
decltype(auto) mybindfront(F&& f, FrontArgs&&...frontArgs)
{
return [f=std::forward<F>(f),
frontArgs = std::make_tuple(std::forward<FrontArgs>(frontArgs)...)]
(auto&&...backArgs)
{
return std::apply(
f,
tuple_append(
frontArgs,
std::forward<decltype(backArgs)>(backArgs)...));
};
}
still passes all test I've provided. I'm keeping old version since with a bit of work it can be tweaked to work with older standard of c++.
Upvotes: 5
Reputation: 10982
One really simpel way I found is with lambda's (in this case capturing this
- but you can change that easily to be generally adoptable):
auto bind_m = [this](auto mem_f) {
auto wrapper = [=] (auto&&... args) {return std::mem_fn(mem_f)(this, std::forward<decltype(args)>(args)...);};
return wrapper;
};
The lambda creates another lambda and returns it.
Upvotes: 0