Call captureless with its type instead of its instance

Viewed 65

I have a code where I can have the type of the lambda, but not its instance, and I want to call it

I tried the following, and obviously, it does not work because operator() is not a static member function...

#include <utility>

template<typename F, typename ...Args>
void call(F, Args&&... args) {
    &F::operator()(std::forward<Args>(args)...);
}

int main() {
    auto is_odd = [](auto x) {return x % 2 == 1;};
    call(is_odd, 5);
}

I tried also to convert it to a function pointer using :

template<typename F, typename ...Args>
void call(F, Args&&... args) {
using return_type = decltype(std::declval<F>()(std::declval<Args&&>()...));
    using ptr = return_type(*)(Args...);
    ptr f = static_cast<ptr>(&F::operator());
    f(std::forward<Args>()...);
}

But it does not work either. Is it possible to do something like that?

1 Answers

In your example you do have an instance. You pass it to your function, it's just that the parameter is not named. The fix is simple: name the parameter and use that:

template<typename F, typename ...Args>
void call(F f, Args&&... args) {
    f(std::forward<Args>(args)...);
}
    
int main() {
    auto is_odd = [](auto x) {return x % 2 == 1;};
    call(is_odd, 5);
}

If for whatever reason you really are in a context where you don't have an instance then are out of luck unless you can use C++20. Before C++20 a lambda is not default constructible so you can't create an instance from it's type. With C++20 you can:


template <typename F, typename... Args>
void call(Args&&... args)
{
    F{}(std::forward<Args>(args)...);
}

int main()
{
    auto is_odd = [](auto x) { return x % 2 == 1; };
    call<decltype(is_odd)>(5);
}
Related