简体   繁体   English

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

[英]How to write a function pointer to a function returning a function pointer to a function?

I want to assign a function's address to a function pointer, but the function to be addressed returns a function pointer with the same signature as itself, causing it to recurse in a way that I can't write the return type at all, for the function pointer or even the function declaration itself... 我想将一个函数的地址赋给一个函数指针,但是要处理的函数返回一个与自身具有相同签名的函数指针,导致它以一种我根本无法写入返回类型的方式递归,因为函数指针甚至函数声明本身......

I guess a way of simplifying the problem so it's not confusing: 我想一种简化问题的方法,所以它不会混淆:

How could I write a function declaration such, that it can return a pointer to itself (or any other function with the same signature)? 我怎么能写一个函数声明,它可以返回一个指向自身的指针(或任何其他具有相同签名的函数)?

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

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

edit: 编辑:

For now I have a solution, though I won't post it as an answer because it's aggressively ugly. 现在我有一个解决方案,但我不会将其作为答案发布,因为它非常难看。 It gets rid of the recursion by simply returning a raw void* pointer as the return type, and ends up taking the following form: 它通过简单地返回一个原始的void*指针作为返回类型来消除递归,并最终采用以下形式:

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

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

edit2: EDIT2:

It seems casting between function pointers and regular pointers is UB, so I can't use void* in this case... 似乎在函数指针和常规指针之间进行转换是UB,所以在这种情况下我不能使用void* ...

To answer one of the comments, this is for passing control between multiple "main" loops in my program, with each loop getting it's own function. 要回答其中一条注释,这是为了在程序中的多个“主”循环之间传递控制,每个循环都获得它自己的功能。 There's a lot of ways to do this, but returning function pointers (or NULL to terminate the program) mid-loop seemed like the simplest method, but I didn't anticipate that pointers to data and pointers to function addresses would be incompatable with each other. 有很多方法可以做到这一点,但返回函数指针(或NULL来终止程序)mid-loop 似乎是最简单的方法,但我没想到指向数据的指针和指向函数地址的指针与每个指针都不相容其他。 I think returning polymorphic function objects will end up being the more sane option in this case. 我认为在这种情况下,返回多态函数对象将最终成为更合理的选项。

Don't use void* , because no guarantee that a void * can hold a function pointer. 不要使用void* ,因为不能保证void *可以保存函数指针。 You can use void(*)() as a workaround: 您可以使用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]: C99 [6.2.5 / 27]:

A pointer to void shall have the same representation and alignment requirements as a pointer to a character type. 指向void的指针应具有与指向字符类型的指针相同的表示和对齐要求。 Similarly, pointers to qualified or unqualified versions of compatible types shall have the same representation and alignment requirements. 同样,指向兼容类型的合格或不合格版本的指针应具有相同的表示和对齐要求。 All pointers to structure types shall have the same representation and alignment requirements as each other. 所有指向结构类型的指针都应具有相同的表示和对齐要求。 All pointers to union types shall have the same representation and alignment requirements as each other. 所有指向union类型的指针都应具有相同的表示和对齐要求。 Pointers to other types need not have the same representation or alignment requirements. 指向其他类型的指针不需要具有相同的表示或对齐要求。

C99 [6.3.2.3/8]: C99 [6.3.2.3/8]:

A pointer to a function of one type may be converted to a pointer to a function of another type and back again; 指向一种类型的函数的指针可以被转换为指向另一种类型的函数的指针并且再次返回; the result shall compare equal to the original pointer. 结果应该等于原始指针。

The trick in C is to take advantage of the fact that any kind of function pointer can be cast to any other kind of function pointer: 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;
}

Each pointer to a strategy is always in a type that can be called once, and the return value is put back into a form that can be called once again. 指向策略的每个指针始终处于可以调用一次的类型中,并且返回值将返回到可以再次调用的表单中。

In C++, you would declare a function object: 在C ++中,您将声明一个函数对象:

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

An instance of this class can be called like a function. 可以像函数一样调用此类的实例。

I suspect what you are trying to do is a more complex version of something like this: 我怀疑你要做的是这样一个更复杂的版本:

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();
    }
}

A workaround is to wrap the function pointer in a 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();
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM