2009-11-19 36 views
7

alguien ya hizo esta pregunta, pero el hilo terminó con la pregunta original sin respuesta.operador con plantilla() sobrecarga C++

suponga que tiene esto:

template<size_t i, class f_type> 
void call_with_i(f_type f); 

functor_type es o bien:

a) una estructura con un método que tiene la firma siguiente:

template<size_t i> operator()() const; 

o, b) una función que se ve así:

template<size_t i> foo(); 

quiero "call_with_i < 42> (foo)" es equivalente a "foo < 42>()", pero no puedo averiguar la sintaxis correcta para que esto suceda. Estaría satified con una solución que hace simplemente (a) pero (a) + (b) sería genial . Ya he probado estas sintaxis:

f<i>(); // doesn't work 
f()<i>; // doesn't work 
f.operator<i>(); // doesn't work 
f.operator()<i>; // doesn't work 
f.operator()<i>(); // works on msvc, but doesn't work on gcc. 

¿Cómo se invoca el operador() con argumentos de plantilla explícitas? ¿Hay alguna manera de invocarlo de modo que la misma sintaxis también llame a una función libre con plantilla?

p.s. Si se está preguntando para qué estoy usando esto, es porque estoy escribiendo una función repeat_to donde repeat_to < 10> (f) invoca f (0) luego f (1) ... f (10). Estoy usando esto para iterar a través de múltiples vectores boost :: fusion en paralelo por índice. Sí, podría usar iteradores, o simplemente podría usar una función de miembro con nombre, pero aún quiero saber la respuesta.

editar nota: me llamó la atención porque pasar una función libre de plantilla como un arg no tiene ningún sentido.

+0

No se respondió porque no puede. – GManNickG

Respuesta

13

La plantilla de miembro es un nombre dependiente, porque su semántica depende del tipo de f_type. Eso significa que debes elegir "plantilla" antes de su nombre (para eliminar la ambigüedad del uso del "menos que" token), similar a cómo se debería poner typename antes de nombres calificados dependientes:

template<size_t i, class f_type> 
void call_with_i(f_type f) { 
    f.template operator()<i>(); 
    // f.template foo<i>(); 
} 

Como solución alternativa, puede utilizar un tipo de ayuda:

template<size_t N> struct size_t_ { }; // or boost::mpl::int_ 

template<size_t i, class f_type> 
void call_with_i(f_type f) { 
    f(size_t_<i>()); 
} 

Ahora, se podría definir su operator() de la siguiente manera:

template<size_t i> void operator()(size_t_<i>) const { 
    // i was deduced automatically by the function argument. 
} 

Esto es muy útil para los constructores con plantilla, para w que no puedes hacer f_type()<i>() o algo así. Serán tienen deducibles en ese caso.

+0

@Johannes: ¿por qué no especializarse para funciones con SFINAE? –

+0

funciona muy bien! completamente asombroso. eres mi metahéroe ah, y tu idea al usar mpl :: int_ también es inteligente. – Glenn

+0

@ laulaulabs.mp, me alegro de ser de ayuda :) –

0
#include <iostream> 

template<size_t i, class f_type> void call_with_i(f_type f); 

struct A { 

    template < size_t i > 
    void operator()() const { 
     /* no link err in demo */ 
    } 

    template < size_t i > 
    void foo() { 
     /* no link err in demo */ 
    } 
}; 

int main(int argc, char * const argv[]) { 
    A f; 

    enum { Constant = 42 }; 

    f.operator()<Constant>(); 
    f.foo<Constant>(); 

    return 0; 
} 

¿Hay una manera de invocar de manera que la misma sintaxis también llamar a una función gratuita de plantilla?

¿Puedes aclarar? (pseudocódigo, o algo así)

+0

en realidad, mi parte acerca de la función de plantilla libre es una tontería ya que no se puede pasar una plantilla de función como argumento. – Glenn

1

En un caso como el tuyo, utilizaría boost :: function como tipo de functor. A continuación, puede pasar tanto los objetos de función como los punteros de función conservando la misma interfaz.