Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Invoke a function/functor with parameters more than arguments

I'd like to write a template function which can invoke a function with given parameters.

For instance, I can write a simple invoke function:

template<class F, class... Args>
inline auto invoke(F &&func, Args&&... args) -> decltype(auto)
{
    return std::forward<F>(func)(std::forward<Args>(args)...);
}

This invoke accepts same count of parameter which f requires. However, I want to this template function allow additional unused parameters. That is, I want to write some code like:

auto f = [] (auto a) {...};
invoke(f, 1, 2, 3);

Here, f accepts only one parameter so, I wish invoke ignore other parameters except the first one. This can be accomplished very easily by get arity of the lambda unless the lambda is generic.

Since f here is generic lambda, as far as I know, there's no general way to figure out arity of f without explicit instantiation of its template operator()<...>.

How can I wirte my invoke?

like image 637
xylosper Avatar asked Oct 26 '25 17:10

xylosper


1 Answers

One possibility:

#include <utility>
#include <cstddef>
#include <tuple>

template <std::size_t... Is, typename F, typename Tuple>
auto invoke_impl(int, std::index_sequence<Is...>, F&& func, Tuple&& args)
    -> decltype(std::forward<F>(func)(std::get<Is>(std::forward<Tuple>(args))...))
{
    return std::forward<F>(func)(std::get<Is>(std::forward<Tuple>(args))...);
}

template <std::size_t... Is, typename F, typename Tuple>
decltype(auto) invoke_impl(char, std::index_sequence<Is...>, F&& func, Tuple&& args)
{
    return invoke_impl(0
                     , std::index_sequence<Is..., sizeof...(Is)>{}
                     , std::forward<F>(func)
                     , std::forward<Tuple>(args));
}

template <typename F, typename... Args>
decltype(auto) invoke(F&& func, Args&&... args)
{
    return invoke_impl(0
                     , std::index_sequence<>{}
                     , std::forward<F>(func)
                     , std::forward_as_tuple(std::forward<Args>(args)...));
}

DEMO

like image 110
Piotr Skotnicki Avatar answered Oct 28 '25 07:10

Piotr Skotnicki



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!