我试图通过Y-combinator在C中引用函数名来写递归.但是,我无法在以下尝试中找出函数的类型:
- #include <iostream>
- using std::cin;
- using std::cout;
- template<class Function> unsigned long factorial1(Function self,unsigned long n) {
- return n ? n * self(self,n - 1) : 1;
- }
- unsigned long factorial(unsigned long n) {
- return factorial1(factorial1,n);
- }
- int main() {
- unsigned long n;
- cin >> n;
- cout << factorial(n) << '\n';
- return 0;
- }
编译器不能推断什么是功能,我也不能.然后我尝试了以下:
- #include <iostream>
- using std::cin;
- using std::cout;
- struct Factorial {
- template<class Function> unsigned long operator()(Function self,unsigned long n) const {
- return n ? n * self(self,n - 1) : 1;
- }
- };
- unsigned long factorial(unsigned long n) {
- return Factorial()(Factorial(),n);
- }
- int main() {
- unsigned long n;
- cin >> n;
- cout << factorial(n) << '\n';
- return 0;
- }
这与上面的例子相比,我将工作函数改为可调用对象,这个函数容易被推导为Factorial,导致以下组合器的完整实现:
- #include <iostream>
- using std::cin;
- using std::cout;
- struct Factorial {
- template<class Function> unsigned long operator()(Function self,n - 1) : 1;
- }
- };
- template<class Function> auto y(Function f) {
- return [f](auto n) {
- return f(f,n);
- };
- }
- int main() {
- unsigned long n;
- cin >> n;
- cout << y(Factorial())(n) << '\n';
- return 0;
- }
问题是,是否可以将struct Factorial重写为一个简单的函数?
解决方法
你这样做稍微有些错误:factorial1的第一个参数应该是具有类型unsigned long(*)(unsigned long)的factorial1的固定点,而不是factorial1本身,因此不需要为自己提供自己的参数:
- unsigned long factorial1(unsigned long(*self)(unsigned long),unsigned long n) {
- return n ? n * self(n - 1) : 1;
- }
C不允许作为函数指针传递闭包,所以我们必须:
>传递std ::函数或其他一些包装器作为自我.不太有意思的海事组织
>使用模板魔术在编译时生成固定点函数.
第二个选择可以轻松完成:
- template<class X,X(*Fn)(X(*)(X),X)>
- struct Fix {
- static X Function(X x) {
- return Fn(Fix<X,Fn>::Function,x);
- }
- };
现在,Fix< unsigned long,factorial1> :: Function is a fixed point of factorial1
:
- unsigned long factorial(unsigned long n) {
- return Fix<unsigned long,factorial1>::Function(n);
- };
请注意,此修复实现仍以名称引用,所以任何实现固定点组合器都不会有类型的系统黑客.