Darius
Darius

Reputation: 727

Parametrize using a template parameter as a parameter to a lambda

I want to be able to have some functor as a parameter to a function.

The functor's parameter is supposed to be templated so I can call other functions that depend on it's type.

Here's what I have so far:

using namespace std;
template<typename T, typename PredT>
void foo(PredT pred)
{
    for(size_t i=0; i< 3; i++)
    {
        std::function<void(T)> predImpl(pred);
        T t{};
        predImpl(t);
    }
}


template<typename T>
void foo2(std::function<void(T)> func)
{
    for(size_t i=0; i< 3; i++)
    {
        T t{}; //there's obviously other logic that produces those;
        func(t);
    }
}

int main()
{     
    //foo([](int x) {cout << x << '\n';}); //error: no matching function for call to 'foo(main()::<lambda(int)>)
    // foo([](int x) {cout << x << '\n';}); doesn't work  error: no matching function for call to 'foo(main()::<lambda(int)>)' 
    foo2(std::function<void(int)>([](int x) {cout << x << '\n';})); // syntax is ugly, requires an explicit conversion to std::function

}

I would basically want to deduce the T based on the parameter to the lambda but I have no idea if that is possible.

The solution using the explicit std::function conversion works but it's cumbersome and kind of looses the convenience of just using a lambda.

Upvotes: 1

Views: 60

Answers (1)

Igor Tandetnik
Igor Tandetnik

Reputation: 52471

If you don't need to support generic lambdas, you can do something like this:

template <typename C, typename R, typename T>
T detectParameterType(R (C::*)(T));
template <typename C, typename R, typename T>
T detectParameterType(R (C::*)(T) const);

template<typename PredT>
void foo(PredT pred)
{
    using T = decltype(detectParameterType(&PredT::operator()));
    T t{};
    pred(t);
}

Demo

Generic lambdas can take parameters of any type, so naturally it's impossible to deduce the parameter type - there's no single type to deduce.

Upvotes: 2

Related Questions