2009-06-02 16 views
13

considere este código simple e inútil.C++ functor y plantillas de funciones

#include <iostream> 

struct A { 
    template<int N> 
    void test() { 
     std::cout << N << std::endl; 
    } 
}; 

int main() { 
    A a; 
    a.test<1>(); 
} 

Es un ejemplo muy simple de una plantilla de función. ¿Qué pasa si, sin embargo, quería reemplazar A::test con un operator() sobrecargado para que sea un functor?

#include <iostream> 

struct A { 
    template<int N> 
    void operator()() { 
     std::cout << N << std::endl; 
    } 
}; 

int main() { 
    A a; 
    a<1>(); // <-- error, how do I do this? 
} 

Ciertamente, si la operator() tomaron parámetros que dependían de la plantilla, el compilador podría deducir la plantilla. Pero simplemente no puedo encontrar la sintaxis adecuada para especificar los parámetros de la plantilla con un functor sin parámetros.

¿Hay una forma adecuada de hacerlo?

Obviamente, este código funcionaría, ya que no pasa por la sintaxis funtor:

a.operator()<1>(); 

pero que derrota un poco con el fin de que sea un funtor :-P.

+0

+1: Sintaxis extraña para usar en la ofuscación de código. Debería mencionarse en http://thc.org/root/phun/unmaintain.html :-) –

Respuesta

9

No hay otra manera "directa" Sé que no sea el:

a.operator()<1>(); 

sintaxis. Si está abierto a cambiar el código, mover el parámetro de plantilla a la clase funcionaría, o usar un (boost | tr1) :: bind para hacer un objeto (boost | tr1) :: function.

24

sólo puede llamar a

a.operator()<1>(); 

pero eso no estaría utilizando un funtor. Los funtores necesitan un operador que no sea de plantilla(), ya que deben poder llamarse como varname() y eso no funcionará con su código.

para que sea un funtor real de cambiar el código de una clase de plantilla (funtores son clases):

#include <iostream> 

template<int N> 
struct A { 
    void operator()() { 
     std::cout << N << std::endl; 
    } 
}; 

int main() { 
    A<1> a; 
    a(); 
} 
2

Usted está tratando de pasar un parámetro de plantilla a una instancia de un objeto, que por lo que yo sé No se permite. Solo puede pasar parámetros de plantillas a funciones de plantilla u objetos de plantilla.

a.test < 1>(); y a.operator() < 1>(); funcionan porque sirven como funciones de plantilla.

Utilice boost :: bind (consulte bibliotecas de boost) para solucionarlo.

struct A { 
    void operator()(int n) { 
     std::cout << n << std::endl; 
    } 
}; 

int main(int argc, char* argv[]) { 
    A a; 
    boost::function<void()> f = boost::bind<void>(a, 1); 
    f(); // prints 1 

    return 0; 
} 

¡Y ni siquiera tiene que meterse con las plantillas!

0

No, no hay forma de evitarlo. Como dijo, debe llamar al operador de forma explícita (lo que infringe el objetivo), o el compilador debe poder deducir los argumentos de la plantilla.

1

Estás atascado. ¿Ha considerado algo como

struct A { 
    template<int N> 
    struct B 
    { 
     void operator()() 
     { std::cout << N << std::endl; } 
    }; 

    template<int N> 
    B<N> functor() {return B<N>();} 
}; 

int main() 
{ 
    A a; 
    a.functor<1>()(); 
} 
Cuestiones relacionadas