Let's say I have a function f like this:
void f(int x) {
cout << "Hi I'm f" << endl;
}
auto x = f;
But if the function is overloaded, this does not works:
void f(int x) {}
void f(int x, const int y) {}
auto x = f; // Which one to use ?
So it's impossible. But let's assume I know which arguments I will pass to the function, for examples I know I want to call f(10, 20). Not the types of the arguments itself, but the actual values, which could differ in constness, reference-ness (assume the word exists...), or even different types by casting. In the example 20 is int&& and the argument const int is bindable. I assume also that there is no edge-cases and the values can only bind to one overload, which also could not compile even by directly call anyway. Is it possible to deduce the address of the overloaded function and the signature of the function ?
Pseudo-code:
Input: Values of arguments
Output: Address of overloaded function `f` OR function signature type (any one can be deduced from the other though)
It is obviously possible to call directly, but the function does "sneak around" and is directly called and looks like to be not possibly referenced.
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
}
Which function gets called depends on the reference-ness/constness of the parameters as you rightly mentioned. You will have to tell the compiler the signature explicitly and then you will be able to get the function pointer. Interestingly this also works for templates.
#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
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With