2009-12-10 11 views
21

Tengo un código que funciona 100% para el caso de uso que tengo. Me pregunto si alguien puede explicar cómo y por qué funciona.Pasar un puntero a una función de miembro como un argumento de plantilla. ¿Por qué funciona esto?

Tengo una clase de plantilla que se encuentra entre algún código que maneja el enhebrado y la comunicación de red y el usuario de la biblioteca para pasar los datos recibidos del servidor al usuario.

template <class Bar, 
      class Baz, 
      class BazReturnType, 
      void (Bar::*BarSetterFunction)(const BazReturnType &), 
      BazReturnType (Baz::*BazGetterFunction)(void) const> 
class Foo 
{ 
    Foo(Bar *bar) 
     : m_bar(bar) 
    { 
    } 

    void FooMemberFunction(const Baz *baz) 
    { 
     boost::bind(BarSetterFunction, m_bar, 
        boost::bind(BazGetterFunction, baz)())(); 
    } 

    Bar *m_bar; 
}; 

Esta plantilla se crea una instancia y se utiliza en la biblioteca en función de los tipos de barra y Baz, así:

typedef Foo<MyBar, 
      MyBaz, 
      ReturnTypeFromBazGetterFunction, 
      &MyBar::ActualSetterFunction, 
      &MyBaz::ActualGetterFunction > 
    MyFoo; 

MyBar *bar = new MyBar; 
MyBaz *baz = new MyBaz; 
MyFoo *f = new MyFoo(bar); 
f->FooMemberFunction(baz); 

funciona todo esto y boost :: bind llama a las funciones de captador/definidor para pasar los datos alrededor de donde tiene que ir. ¿Cómo y por qué pasa punteros a funciones miembro como un argumento de plantilla como en este caso?


En respuesta a los comentarios, no me había dado cuenta de que los punteros a funciones miembro son válidos argumentos de plantilla. No es algo que haya visto "en la naturaleza" antes. Lo intenté y funcionó, pero no esperaba que lo hiciera.

+1

No estoy seguro de entender exactamente lo que me está preguntando. Un puntero al miembro es uno de los tipos permitidos de parámetro de plantilla sin tipo. ¿Estás buscando una referencia a esto en el estándar? 14.1/4 [templ.param] –

Respuesta

34

Creo que hay una mejor explicación de por qué es posible hacerlo que "debido a que la norma dice así":

La razón funciona es porque los punteros-a-miembros son valores constantes conocidos en tiempo de compilación (puntero a miembro es efectivamente un desplazamiento de un miembro desde el inicio de una clase). Por lo tanto, se pueden usar como parámetros de plantillas, al igual que cualquier otra constante entera.

Por otro lado, los punteros normales no son constantes de tiempo de compilación, ya que dependen del diseño de memoria que solo existe en el tiempo de ejecución. No pueden ser argumentos de plantilla.

+9

+1 Te saludo por tu primera oración. – Mehrdad

2

Cuando hace una pregunta como "¿por qué funciona algo?", Implica que el hecho de que funcione de alguna manera es sorprendente para usted. Es imposible responder a la pregunta a menos que explique por qué le resulta sorprendente.

¿Por qué funciona? Porque la especificación del lenguaje dice explícitamente que funcionará. No hay otra respuesta, hasta que explique sus preocupaciones con más detalle.

+0

Supongo que "porque la especificación del lenguaje lo dice" es la respuesta. No me había dado cuenta de que los punteros a las funciones de miembro eran argumentos de plantilla válidos según el estándar. –

Cuestiones relacionadas