返回函数指针到自身

Return Function Pointer to Self?

本文关键字:指针 函数 返回      更新时间:2023-10-16

下面的代码无法编译。但是有没有办法让一个函数指针返回另一个与自身等效的函数指针呢?

typedef FunctionPtr (*FunctionPtr)(int, int);
FunctionPtr Second(int, int);
FunctionPtr First(int, int)
{
    // do something
    return Second;
}
FunctionPtr Second(int, int)
{
    // do something
    return First;
}
int main()
{
    FunctionPtr a = First(1, 2);
    FunctionPtr b = a(2, 3);
    FunctionPtr c = b(4, 5);
    c(5, 6);
}

简短的回答:不,你不能直接这样做。您可以使用 void 指针接近,但它是非标准的,因为 void 指针不能保证足够大以适合函数指针。详见本周大师#57。

最接近标准兼容的方法是为函数指针定义包装器类型:

 struct Wrapper;
 typedef Wrapper (*FunctionPtr)(int, int);
 struct Wrapper {
    Wrapper(FunctionPtr ptr): wrapped(ptr) { }
    operator FunctionPtr() { return wrapped; }
    FunctionPtr wrapped;
 };

现在你可以写:

Wrapper Second(int, int);
Wrapper First(int, int) {
    // do something
    return Second;
}
Wrapper Second(int, int) {
    // do something
    return First;
}
int main() {
    FunctionPtr a = First(1, 2);
    FunctionPtr b = a(2, 3);
    FunctionPtr c = b(4, 5);
    c(5, 6);
}

这里有一些聪明的C++解决方案,但我一直看到的纯C解决方案是只使用一点强制转换:

typedef void (*func)(void);
func myfunc(int, int) { return (func)myfunc); }
// optional
typedef func (*myfunctype)(int, int);
// calling code
myfunctype x = myfunc;
while(x) x = (myfunctype)x(2, 3);

该标准要求强制转换为另一种函数指针类型的函数指针等于原始函数指针,从而使此代码完全可靠。

这是我

在大约 15 分钟内到达的最接近的一次......

#include <stdio.h>
struct container
{
    typedef container (*Ptr)(int, int);
    const Ptr _ptr;
    explicit container(Ptr ptr) : _ptr(ptr) { }
    operator Ptr() const { return _ptr; }
};
struct container narcissus(int a, int b)
{
  printf("Narcissus: %i %i.n", a, b);
  return container(narcissus);
}
int main(void)
{
  narcissus(3, 4)(5, 6)(7, 8);
  return 0;
}

现在,使这个婴儿成为 N 个参数的泛型,作为练习留给读者:)

由于类型检查,这是不可能的。这将要求编译器在其类型检查中解决固定点,而目前编译器无法做到这一点。

您可以做的最接近的是通过继承抽象出返回类型:

template<class T>
class Function { public: virtual void Map(T t)=0; };
template<class T, class K>
class FunctionPtr : public Function<T> {
public:
  FunctionPtr(K (*fptr)(T)) : fptr(fptr) { }
  void Map(T t) { fptr(t); }
private:
  K (*fptr)(T);
};
Function<int> *my_function(int i)
{
   return new FunctionPtr<int,Function<int>*>(&my_function);
}