如何编写一个函数指针,返回一个返回函数指针的函数?

时间:2015-09-27 15:04:48

标签: c++ function pointers

我想将一个函数的地址赋给函数指针,但是要处理的函数返回一个与自身具有相同签名的函数指针,导致它以一种我无法写入返回类型的方式递归,对于函数指针甚至函数声明本身......

我想这是一种简化问题的方法,因此不会让人感到困惑:

我怎么能写一个函数声明,它可以返回一个指向自身的指针(或任何其他具有相同签名的函数)?

????? function(int a){
    // could be this function, or another with the same signature, 
    return arbitraryFunction;  
}

?????(*func)(int) = function;  // same problem as above

修改

现在我有一个解决方案,但我不会将其作为答案发布,因为它非常难看。它通过简单地返回原始void*指针作为返回类型来消除递归,并最终采用以下形式:

void* function(int parameter){
    return arbitraryFunction; // of the same signature
}

void*(*func)(int) = function; 
func = reinterpret_cast<void*(*)(int)>(func(42));  // sin

EDIT2:

似乎在函数指针和常规指针之间进行转换是UB,所以在这种情况下我不能使用void* ...

要回答其中一条注释,这是为了在我的程序中的多个“主”循环之间传递控制,每个循环都获得它自己的功能。有很多方法可以做到这一点,但返回函数指针(或NULL来终止程序)中间循环似乎就像最简单的方法,但我没有预料到指向数据和指针的指针函数地址彼此无法匹配。我认为在这种情况下,返回多态函数对象将最终成为更合理的选项。

3 个答案:

答案 0 :(得分:6)

不要使用void*,因为无法保证void *可以保存函数指针。您可以使用void(*)()作为解决方法:

typedef void(*void_func)();
typedef void_func (*func_type) (int);
void_func arbitraryFunction(int a) {
    // could be this function, or another with the same signature, 
    cout << "arbitraryFunction\n";
    return nullptr;  
}
void_func function(int a) {
    // could be this function, or another with the same signature, 
    return (void_func) arbitraryFunction;  
}
int main() {
    // your code goes here
    func_type f = (func_type) function(0);
    f(0);
    return 0;
}

LIVE

C99 [6.2.5 / 27]:

  

指向void的指针应具有与指向字符类型的指针相同的表示和对齐要求。同样,指向   兼容类型的合格或不合格版本应具有   相同的表示和对齐要求。所有指针   结构类型应具有相同的表示和对齐方式   彼此的要求。所有指向union类型的指针都应该有   相同的表示和对齐要求。指针   其他类型不需要具有相同的表示或对齐   要求。

C99 [6.3.2.3/8]:

  

指向一种类型的函数的指针可以转换为指向另一种类型的函数的指针,然后再返回;结果应该比较   等于原始指针。

答案 1 :(得分:5)

C中的技巧是利用任何类型的函数指针都可以转换为任何其他类型的函数指针这一事实:

#include <stdlib.h>
#include <stdio.h>

typedef void(*emptyfunc)(void);
typedef emptyfunc (*funcptr2)(int);

funcptr2 strategy(int m)
{
  printf("Strategy %d.\n", m);
  return (funcptr2)&strategy;
}

int main (void)
{
  const funcptr2 strategy2 = (funcptr2)strategy(1);
  const funcptr2 strategy3 = (funcptr2)strategy2(2);
  strategy3(3);

  return EXIT_SUCCESS;
}

指向策略的每个指针始终处于可以调用一次的类型中,并且返回值将被放回可以再次调用的表单中。

在C ++中,您将声明一个函数对象:

class strategy {
  public:
  virtual const strategy& operator()(int) const = 0;
}

可以像函数一样调用此类的实例。

答案 2 :(得分:1)

我怀疑你要做的是这样一个更复杂的版本:

typedef MainLoop *MainLoop(); // not legal

extern MainLoop* main_loop_1();
extern MainLoop* main_loop_2();

MainLoop* main_loop_1()
{
    // do some work here
    return main_loop_2;
}

MainLoop* main_loop_2()
{
    // do some work here
    return main_loop_1;
}

int main()
{
    MainLoop f = main_loop_1;

    for (;;) {
      f = f();
    }
}

解决方法是将函数指针包装在struct:

struct MainLoop {
    MainLoop (*function_ptr)(); // legal
};

extern MainLoop main_loop_1();
extern MainLoop main_loop_2();

MainLoop main_loop_1()
{
    // do some work here
    return {main_loop_2};
}

MainLoop main_loop_2()
{
    // do some work here
    return {main_loop_1};
}  

int main()
{
    MainLoop f{main_loop_1};

    for (;;) {
       f = f.function_ptr();
    }
}