C++ Overloaded Method Pointer

How do I specify a pointer to an overloaded function?

You can use static_cast<>() to specify which f to use according to the function signature implied by the function pointer type:

// Uses the void f(char c); overload
std::for_each(s.begin(), s.end(), static_cast<void (*)(char)>(&f));
// Uses the void f(int i); overload
std::for_each(s.begin(), s.end(), static_cast<void (*)(int)>(&f));

Or, you can also do this:

// The compiler will figure out which f to use according to
// the function pointer declaration.
void (*fpc)(char) = &f;
std::for_each(s.begin(), s.end(), fpc); // Uses the void f(char c); overload
void (*fpi)(int) = &f;
std::for_each(s.begin(), s.end(), fpi); // Uses the void f(int i); overload

If f is a member function, then you need to use mem_fun, or for your case, use the solution presented in this Dr. Dobb's article.

C++ overloaded method pointer

(void (A::*)()) &A::f
(void (A::*)(int)) &A::f

function pointers and member function pointers have this feature - the overload can be resolved by to what the result was assigned or cast.

If the functions are static, then you should treat them as ordinary functions:

(void (*)()) &A::f;
(void (*)(int)) &A::f;

or even

(void (*)()) A::f;
(void (*)(int)) A::f;

Disambiguate overloaded member function pointer being passed as template parameter

The issue is here:

l.call(&foo::func, "hello");
l.call(&foo::func, 0.5);

For both lines, the compiler doesn't know which foo::func you are referring to. Hence, you have to disambiguate yourself by providing the type information that is missing (i.e., the type of foo:func) through casts:

l.call(static_cast<void (foo::*)(const std::string&)>(&foo::func), "hello");
l.call(static_cast<void (foo::*)(const double )>(&foo::func), 0.5);

Alternatively, you can provide the template arguments that the compiler cannot deduce and that define the type of func:

l.call<void, const std::string&>(&foo::func, "hello");
l.call<void, double >(&foo::func, 0.5);

Notice that you have to use double and not const double above. The reason is that generally double and const double are two different types. However, there's one situation where double and const double are considered as if they were the same type: as function arguments. For instance,

void bar(const double);
void bar(double);

are not two different overloads but are actually the same function.

Pass a function pointer of an overloaded member function?

Member function pointer and non-member function pointer are not the same thing. The type for member function pointer in your code is not correct, change it to

myObject = new Object(static_cast<void(myclass::*)()>(&myclass::repaint);
~~~~~~~~~

BTW: The void in parameter list is redundant.

Get pointer to overloaded function that would be called

There is no way to get the function of an overload-set which would be called with the given arguments, unless you already know its signature.

And if you know, what's the point?

The problem is that for any given arguments, taking into account implicit conversions, references, cv-qualifiers, noexcept, old-style vararg, default arguments, and maybe also literal 0 being a null pointer constant, there are an infinite number of function-signatures which would match. And there is currently no facility for "just" listing all candidates.

Overload a pointer to an overloaded function

Why are you doing this? Function pointers are for runtime polymorphism based on application state. Plain old overloads work fine if, the only variance is the argument type.

If you want to be able to, say write a library that will call overloads defined later, in client code, do something like the following:

void foo(int x) { printf("int\n");}
void foo(const char* c){ printf("char*\n"); }

template <class T> void callfoo(T t) { foo(t); }

int main(int argc, char* argv[])
{
int x = 3;
callfoo(x);

const char* p = "Hello world";
callfoo(p);

return 0;
}

This allows the lib to call overloads for types it is not actually aware of until link time.

C++ overloaded function pointer ambiguity

Once you fix the typos, the main problem is that you're trying to cast a member function pointer to a function pointer.

That is, the following is illegal:

static_cast<uint32_t(*)(double)>(&Sample::method)
error: invalid static_cast from type 
‘uint32_t (Sample::*)(double) {aka unsigned int (Sample::*)(double)}’
to type
‘uint32_t (*)(double) {aka unsigned int (*)(double)}’

The syntax for a member function pointer is

ReturnT(ClassT::*)(ArgTs);

So your cast would have to be:

static_cast<uint32_t(Sample::*)(double)>(&Sample::method)

Example:

#include <iostream>
#include <functional>

struct Sample
{
uint32_t method(char* input1, double input2) { return 0; }
uint32_t method(double input1) { return 0; }
};

template<class T, class... Args>
void processInput(T &&t, Args&&... a)
{
auto task = std::bind(t, a...);
(void)task;
}

int main()
{
Sample* obj = new Sample();
processInput(static_cast<uint32_t(Sample::*)(double)>(&Sample::method), obj, 2.0f);

return 0;
}

Bad type deduction when passing overloaded function pointer and its arguments

Theory

For each function template Invoke, the template argument deduction (that must succeed for overload resolution to consider it) considers each Foo to see whether it can deduce however many template parameters (here, two) for the one function parameter (func) involved. The overall deduction can succeed only if exactly one Foo matches (because otherwise there is no way to deduce S). (This was more or less stated in the comments.)

The first (“by value”) Invoke never survives: it can deduce from any of the Foos. Similarly, the second (“non-const reference”) overload accepts the first two Foos. Note that these apply regardless of the other argument to Invoke (for arg)!

The third (const T&) overload selects the corresponding Foo overload and deduces T=int; the last does the same thing with the last overload (where T&& is a normal rvalue reference), and therefore rejects lvalue arguments despite its universal reference (which deduces T as int& (or const int&) in that case and conflicts with func’s deduction).

Compilers

If the argument for arg is an rvalue (and, as usual, isn’t const), both plausible Invoke overloads succeed at deduction, and the T&& overload should win (because it binds an rvalue reference to an rvalue).

For the case from the comments:

template <typename U>
void Bar (U &&);
int main() {
int num;
Invoke<void>(&Bar, num);
}

No deduction takes place from &Bar since a function template is involved, so T is successfully deduced (as int) in every case. Then, deduction happens again for each case to identify the Bar specialization (if any) to use, deducing U as fail, int&, const int&, and int& respectively. The int& cases are identical and plainly better, so the call is ambiguous.

So Clang is right here. (But there’s no “undefined behavior” here.)

Solution

I don’t have a general answer for you; since certain parameter types can accept multiple value-category/const-qualification pairs, it’s not going to be easy to emulate overload resolution correctly in all such cases. There have been proposals to reify overload sets in one way or another; you might consider one of the current techniques along those lines (like a generic lambda per target function name).

C++ address of overloaded function

The easiest solution is to store the pointer to the overloaded function in a pointer, first:

#include <cstdio>

static void test0(void)
{
printf("%s [%d]\n", __func__, __LINE__);
}

static void test0(int a)
{
printf("%s [%d] %d\n", __func__, __LINE__, a);
}

int main(void) {
void (*select1)(void) = test0; // will match void(void)
void (*select2)(int) = test0; // will match void(int)

select1();
select2(42);

return 0;
}

$ ./a.out

test0 [5]

test0 [10] 42

If you want to call the stored void*, then you have to make it a function pointer again. You can do that by e.g. reinterpret_cast<void(*)(int)>(p).

C++ passing overloaded operator() of class as function pointer

Supposing that you have to use a function pointer, and that your functor has no state, you can use a lambda as glue:

void takesFunctionPointer(void (*)());

struct MyFunctor {
void operator()();
};

// ...

takesFunctionPointer([] { return MyFunctor{}(); });


Related Topics



Leave a reply



Submit