2012-09-21 25 views
7

Las funciones miembro tienen un parámetro de puntero implícito this. ¿Por qué std::function acepta esta firma, entonces, donde S es una clase simple? (complete sample)¿Por qué std :: function acepta una referencia en la firma?

std::function<void(S &)> func = &S::foo; 

Calling es que funciona, también, y distingue los objetos:

S s1 = {5}; 
S s2 = {6}; 

func(s1); //prints 5 
func(s2); //prints 6 

Lo que normalmente se esperaría es que necesita un puntero, que funciona así: (complete sample)

std::function<void(S * const)> func = &S::foo; 

S s1 = {5}; 
S s2 = {6}; 

func(&s1); //prints 5 
func(&s2); //prints 6 

¿Por qué la primera funciona cuando paso una referencia a la función miembro cuando el parámetro implícito this es un puntero?

Respuesta

3

std::function<SIG> puede construirse a partir de muchas cosas que se comportan como funciones, convirtiéndolas en un objeto apropiado std::function.

En este caso void S::foo() se comporta como una función void foo_x(S&) (como en ambos requieren un S a llamar, y potencialmente modifican S, nada de vuelta). En consecuencia, std::function<void(S&)> proporciona un constructor para convertir la función miembro en un objeto de función. Es decir.

std::function<void(S &)> func = &S::foo; 

utiliza un constructor, algo así como std::function<void(S&)>(void(S::)()), para crear algo equivalente a:

void foo_x(S & s) { return s.foo(); } 
std::function<void(S&)> func = foo_x; 

Del mismo modo,

std::function<void(S * const)> func = &S::foo; 

es equivalente a

void foo_x(S * const s) { return s->foo(); } 
std::function<void(S* const)> func = foo_x; 

a través de una constructor como std::function<void(S* const)>(void(S::)()).

+2

Eso fue una lectura muy informativa, gracias. Tiene mucho más sentido cuando se considera que 'std :: function' es independiente de los punteros de función sin procesar y tiene el poder de hacer lo que quiera para aumentar la usabilidad de lo que está envolviendo. – chris

5

Porque std::function está correctamente diseñado. El hecho de que this sea un puntero es un accidente de historial y un detalle interno de la función de miembro. El hecho no debería tener impacto en las decisiones de diseño de los usuarios de la función.

Los diseñadores de std::function decidieron, con razón, aceptar funciones miembro cuando el primer tipo de parámetro en la firma es una referencia.

Cuestiones relacionadas