如何从参数中获取函数签名?

How to get function signature from arguments?

本文关键字:函数 获取 参数      更新时间:2023-10-16

假设我有一个这样的函数f

void f(int x) {
cout << "Hi I'm f" << endl;
}
auto x = f;

但是如果函数重载,这不起作用:

void f(int x) {}
void f(int x, const int y) {}
auto x = f; // Which one to use ?

所以这是不可能的。但是,让我们假设我知道我将向函数传递哪些参数,例如我知道我想调用f(10, 20)。不是参数本身的类型,而是实际值,它们可能在恒定性、引用性(假设这个词存在......(方面有所不同,甚至通过强制转换的不同类型。在示例中,20int&&的,参数 const int 是可绑定的。我还假设没有边缘情况,值只能绑定到一个重载,即使直接调用也无法编译。是否可以推断出重载函数的地址和函数的签名?

伪代码:

Input: Values of arguments
Output: Address of overloaded function `f` OR function signature type (any one can be deduced from the other though)

显然可以直接调用,但该函数确实"潜行"并且被直接调用,看起来不可能被引用。

template<typename... Args>
void callMeMaybe(Args... args) {
f(args...); // I can call f... But how to get f itself ?
auto x = static_cast<void(Args...)>(f) // does not works because f could differ in argument bind
}

调用哪个函数取决于您正确提到的参数的引用性/恒定性。您必须显式告诉编译器签名,然后您将能够获取函数指针。有趣的是,这也适用于模板。

#include<iostream>
template<typename Name1, typename Name2, typename Name3>
Name3 f(Name1, Name2, Name3);
int f(int);
int f(int,int const);
using namespace std;
int main()
{
//Type deduction using decltype: the args must be constexpr.
//Remember there is no runtime-reflection support in c++ yet.
auto s = static_cast< int (*)(decltype(78), decltype(-98) ) > (f);
cout << s(78, -98) << endl;
cout << typeid(s).name() << endl;
// x and y will point to the same function
// int (*)(int) and int (*)(const int) are equivalent overloads
auto x = static_cast<int (*)(int)>( f );
auto y = static_cast<int (*)(int const)>( f );
//p and q will point to the same function
// int (*)(int, int) and int (*)(int, const int) are equivalent overloads
auto p = static_cast<int (*)(int, int const)>( f );
auto q = static_cast<int (*)(int, int)>( f );
//With templates
auto z = static_cast<string (*)(int, char, string)>( f );
cout << z(4,'a',"Hello!!") << endl;
//typeid to check signatures
cout << typeid(x).name() << endl;
cout << typeid(y).name() << endl;
cout << typeid(p).name() << endl;
cout << typeid(q).name() << endl;
cout << typeid(z).name() << endl;
return 0;
}
int f(int arg)
{
return arg;
}
int f(int a1, int const a2)
{
return a2; //Return the second element
}
template<typename Name1, typename Name2, typename Name3>
Name3 f(Name1 a, Name2 b, Name3 c)
{
return c; // Return the 3rd element
}