zl程序教程

您现在的位置是:首页 >  后端

当前栏目

C++实现的一个可以写递归lambda的Y函数

C++递归 实现 函数 一个 可以 lambda
2023-06-13 09:15:38 时间

最近学习C++11的variadictemplateargument,终于可以摆脱用fpmacro模板来复制一大堆代码的做法了,好开心。这个例子的main函数用lambda写了一个斐波那契数列的递归计算函数。跟以往不同的是,在Y函数的帮助下,这个lambda表达是可以成功看到自己,然后递归调用。当然这仍然需要用普通的C++递归来实现,并不是λ-calculus那个高大上的YCombinator。

#include<functional>
#include<memory>
#include<iostream>
#include<string>

usingnamespacestd;

template<typenameTResult,typename...TArgs>
classYBuilder
{

private:

function<TResult(function<TResult(TArgs...)>,TArgs...)>partialLambda;

public:

YBuilder(function<TResult(function<TResult(TArgs...)>,TArgs...)>_partialLambda)

:partialLambda(_partialLambda)

{

}

TResultoperator()(TArgs...args)const

{

returnpartialLambda(

[this](TArgs...args)

{

returnthis->operator()(args...);

},args...);

}

};

template<typenameTMethod>

structPartialLambdaTypeRetriver

{

typedefvoidFunctionType;

typedefvoidLambdaType;

typedefvoidYBuilderType;

};

template<typenameTClass,typenameTResult,typename...TArgs>

structPartialLambdaTypeRetriver<TResult(__thiscallTClass::*)(function<TResult(TArgs...)>,TArgs...)>
{

typedefTResultFunctionType(TArgs...);

typedefTResultLambdaType(function<TResult(TArgs...)>,TArgs...);

typedefYBuilder<TResult,TArgs...>YBuilderType;

};


template<typenameTClass,typenameTResult,typename...TArgs>

structPartialLambdaTypeRetriver<TResult(__thiscallTClass::*)(function<TResult(TArgs...)>,TArgs...)const>

{

typedefTResultFunctionType(TArgs...);

typedefTResultLambdaType(function<TResult(TArgs...)>,TArgs...);

typedefYBuilder<TResult,TArgs...>YBuilderType;

};



template<typenameTLambda>

function<typenamePartialLambdaTypeRetriver<decltype(&TLambda::operator())>::FunctionType>Y(TLambdapartialLambda)

{

returntypenamePartialLambdaTypeRetriver<decltype(&TLambda::operator())>::YBuilderType(partialLambda);

}



int_tmain(intargc,_TCHAR*argv[])

{

autofib=Y([](function<int(int)>self,intindex)

{

returnindex<2

?1

:self(index-1)+self(index-2);

});



for(inti=0;i<10;i++)
{

cout<<fib(i)<<"";

}

cout<<endl;

}