Пара возможных ответов:
- тип-стирание;на самом деле вам не нужно знать тип функции recursiveFunction, достаточно просто закрепить ее подпись.
Так что вы можете просто обойтись без проблемного auto
и связанного с ним вывода и пообещать знатьтип заранее.
template <class T>
int Class<T>::foo(int x) {
std::function<int(int)> recursiveFunction;
recursiveFunction = [=](int n)->int {
if (n <= 1) return 1;
else return n*recursiveFunction(n-1);
};
return recursiveFunction(x);
}
Если это был не просто упрощенный пример, вы, похоже, фактически не захватываете какое-либо состояние, поэтому вы можете просто использовать обычную рекурсивную функцию вместо лямбды.
namespace {
int recursiveFunction(int) {
if (n <= 1) return 1;
else return n*recursiveFunction(n-1);
}
}
int Class<T>::foo(int x) {
return recursiveFunction(x);
}
Если лямбда-аспект был действительно важен, вы ищете "Y комбинатор". Что не очень просто в C ++, но что-то вроде:
#include <iostream>
#include <functional>
template <class T>
class Class {
public:
int foo(int x);
};
template<class F>
struct function_traits;
template<class R, class T>
struct function_traits<R(T)> {
typedef R return_type;
typedef T arg_type;
};
// function pointer
template<class R, class... Args>
struct function_traits<R(*)(Args...)> : public function_traits<R(Args...)>{}};
template <typename Signature>
auto y (std::function<typename function_traits<Signature>::return_type(typename function_traits<Signature>::arg_type, std::function<Signature>)> f)
-> std::function<Signature>
{
return [f](typename function_traits<Signature>::arg_type n) -> typename function_traits<Signature>::return_type { return f(n,y(f)); };
}
template <class T>
int Class<T>::foo(int x) {
return y<int(int)>([=](int n, auto recursiveFunction) -> int {
if (n <= 1) return 1;
else return n*recursiveFunction(n-1);
})(5);
}
int main() {
Class<int> c;
std::cout << c.foo(5) << std::endl;
return 0;
}