29

How do I get a method pointer to a particular overload of a method:

struct A {
    void f();
    void f(int);
    void g();
};

I know that

&A::g

is a pointer to g. But how do I get a pointer to f or f(int)?

jwueller
  • 30,582
  • 4
  • 66
  • 70
Neil G
  • 32,138
  • 39
  • 156
  • 257

3 Answers3

37
(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;
Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434
  • Thanks! What if the member functions are static? (I am getting `error: address of overloaded function with no contextual type information`) – Neil G Dec 06 '10 at 08:54
  • Oh, I see, I just get rid of the first `A::` for static functions, since they can be cast to regular pointers. You beat me to it :) – Neil G Dec 06 '10 at 08:58
  • 1
    Also, you don't need the cast in an initialization, for example `void (A::*func)() = &A::f;` – Steve Jessop Dec 06 '10 at 08:59
  • 1
    Your C-style casts can bite you if you e.g. forget to include a header where the needed overload is declared, while the other function would thus be unambiguous, as in this case the cast will effectively be `reinterpret_cast` and will silently compile leading to UB. – Ruslan Aug 19 '16 at 12:16
  • The unusual selection of the overloaded member based on the cast or the type of the assigned-to variable appears spelled in [\[over.over\]](https://timsong-cpp.github.io/cppwp/n4861/over.over), `A use of a function name without arguments is resolved to a function, a pointer to function, or a pointer to member function [..] based on the target type [..]`. – eel ghEEz May 13 '22 at 05:20
9

You just have to cast the result of &A::f in order to remove the ambiguity :

static_cast<void (A::*)()>(&A::f); // pointer to parameterless f
static_cast<void (A::*)(int)>(&A::f); // pointer to f which takes an int
icecrime
  • 74,451
  • 13
  • 99
  • 111
5

Thanks to Stefan Pabst for the following idea, which he presented in a five minute lightning talk at ACCU 2015. I extended it with tag types to allow for resolving overloads by their cv qualifier and/or reference qualifier, and a C++17 variable template to avoid having to type the extra pair of parentheses which is otherwise required.

This solution works on the same principle as the cast-based answers, but you avoid having to restate either the return type of the function or, in the case of member functions, the name of the class which the function is a member of, as the compiler is able to deduce these things.

bool free_func(int, int) { return 42; }
char free_func(int, float) { return true; }
struct foo {
    void mem_func(int) {}
    void mem_func(int) const {}
    void mem_func(long double) const {}
};

int main() {
    auto f1 = underload<int, float>(free_func);
    auto f2 = underload<long double>(&foo::mem_func);
    auto f3 = underload<cv_none, int>(&foo::mem_func);
    auto f4 = underload<cv_const, int>(&foo::mem_func);
}

The code implementing the underload template is here.

Oktalist
  • 14,336
  • 3
  • 43
  • 63