如何从任何可调用的函数中获取有意义的函数签名

How to get a meaningful function signature from anything callable

提问人:sbi 提问时间:8/19/2014 最后编辑:David Gsbi 更新时间:8/19/2014 访问量:543

问:

想想这样的野兽:

template<typename Func>
void register_function(Func func) {
  // type-erase Func and pass it on to some other function
}

假设这可以传递任何可调用的东西。

如果是普通函数类型,我知道如何获取函数的签名。假设它可以是普通函数、函数或函数对象(表达式),我该如何获取函数的参数?Funcfuncstd::function<F>std::bind()

注意:

  • 在这种情况下,函数只有零个、一个或两个参数
  • 如果它是一个函数对象,它是std::bind()
  • 为了获取参数的类型,需要签名,这些类型需要在传递的类型擦除的东西中使用

  • 这是严格的 C++03(嵌入式平台),因此没有变量模板参数等。

C++ 函数 模板-元编程

评论

2赞 Xeo 8/19/2014
对不起,但这在一般情况下是不可能的。您应该知道,在注册站点上,您将向回调传递哪些类型的参数。
3赞 Some programmer dude 8/19/2014
如果它严格是 C++03,那么你无法获得 std::function 对象。
2赞 Puppy 8/19/2014
boost::function 或 std::tr1::function 具有相同的目的。
0赞 Niall 8/19/2014
就像在带有嵌入名称的部分模板中一样?
0赞 jweyrich 8/19/2014
我认为你不能重复 F 的论点。

答:

10赞 Puppy 8/19/2014 #1

不可能的。函数对象可以重载或模板化。因此,它具有“签名”的想法根本不适用,因为它可以具有无限数量的签名。operator()

如果将其限制为只有一个签名,则可以获取 operator() 的地址,然后使用常规模板专用化从成员函数指针类型获取参数。

评论

0赞 sbi 8/19/2014
好吧,我没有想到过载的函子.不过,它在这里并不适用。如果它是一个函子,它是 的结果,并且只有一个重载。operator()std::bind()
1赞 Puppy 8/19/2014
std::bind生成模板化 S。operator()
0赞 sbi 8/19/2014
是的,我不知道如何推断这些,也不知道如何区分所有可能性,以便使用正确的机制来破解签名。
0赞 Basile Starynkevitch 8/19/2014 #2

如果你在运行时知道某个被调用的(普通)函数的签名,你可以使用(特别是在 Linux 上)libffi 来调用它。

如果你在运行时甚至不知道要调用的函数的签名,那是不可能的,因为一般来说,ABI 约定会根据函数参数的类型来规定传递函数参数的不同方式。

例如,x86-64 ABI(在大多数 Linux 64 位 x86-64 系统上遵循)要求在不同的寄存器集中传递浮点值和整数值。

例如,请参阅 x86 调用约定 wikipage。

评论

1赞 sbi 8/19/2014
我提到了类型擦除。为此,我需要编译时的类型。方便的是,我也在编译时提供了它们,因为它们嵌入在 的签名中。我只需要破解它.在编译时。FF