2010-12-06 21 views
25

¿Cómo puedo obtener un puntero a una sobrecarga método particular de un método:C++ sobrecargado método puntero

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

sé que

&A::g 

es un puntero a g. ¿Pero cómo consigo un puntero a f o f(int)?

Respuesta

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

punteros de función y los punteros de función miembros tienen esta característica - la sobrecarga puede ser resuelto por lo que se le asignó o yeso el resultado.

Si las funciones son estáticas, entonces usted debe tratarlos como funciones ordinarias:

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

o incluso

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

Gracias! ¿Qué pasa si las funciones miembro son estáticas? (Estoy obteniendo el 'error: dirección de la función sobrecargada sin información de tipo contextual') –

+0

@Neil: ver mi edición –

+0

Oh, ya veo, me deshago del primer' A :: 'para las funciones estáticas, ya que pueden ser lanzado a punteros regulares. Me ganaste :) –

9

Sólo tiene que emitir el resultado de &A::f con el fin de eliminar la ambigüedad :

static_cast<void (A::*)()>(&A::f); // pointer to parameterless f 
static_cast<void (A::*)(int)>(&A::f); // pointer to f which takes an int 
+0

Imho es una de las mejores publicaciones publicadas en el SE sobre C++ ... – peterh

5

Gracias a Stefan Pabst por la siguiente idea, wh que presentó en una charla relámpago de cinco minutos en ACCU 2015. Lo amplié con tipos de etiquetas para permitir la resolución de sobrecargas por su calificador de cv y/o calificador de referencia, y una plantilla variable de C++ 17 para evitar tener que escribir el par adicional de paréntesis que de otro modo se requiere.

Esta solución funciona según el mismo principio que las respuestas basadas en el molde, pero evita tener que repetir el tipo de retorno de la función o, en el caso de funciones miembro, el nombre de la clase que la función es miembro de, como el compilador es capaz de deducir estas cosas.

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); 
} 

El código de la aplicación de la plantilla de underload es here.

Cuestiones relacionadas