Параметризация с использованием параметра шаблона в качестве параметра лямбды - PullRequest
1 голос
/ 16 марта 2020

Я хочу иметь возможность использовать некоторый функтор в качестве параметра функции.

Предполагается, что параметр функтора является шаблонным, поэтому я могу вызывать другие функции, которые зависят от его типа.

Вот что у меня есть:

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

}

Я бы хотел вывести T на основе параметра для лямбды, но я не знаю, возможно ли это.

Решение, использующее явное преобразование std::function, работает, но оно громоздко и отчасти лишает удобства простого использования лямбды.

1 Ответ

2 голосов
/ 17 марта 2020

Если вам не требуется поддержка родовых c лямбд, вы можете сделать что-то вроде этого:

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);
}

Демо

Generi c Лямбда может принимать параметры любого типа, поэтому, естественно, невозможно определить тип параметра - нет единственного типа для вывода.

...