2011-11-22 13 views
5

He estado jugando con las plantillas variadic en el nuevo estándar de C++ y se acercó con una función de mapa (+ cabeceras usando dism excluidos):C++ mapa de funciones aplicación

template<typename T> 
T square(T i) 
{ 
     return i * i; 
} 

template <typename T, typename... Ts> 
const tuple<Ts...> map(const T f, const Ts...args) 
{ 
     return make_tuple(f(args)...); 
} 

int main(int c, char *argv[]) 
{ 
     tuple<int, int> t; 
     int (*fp) (int) = square; 

     t = map(fp, 6, 8); 

     cout <<get<0>(t) <<endl; 
     cout <<get<1>(t) <<endl; 

     return 0; 
} 

que trabaja. Siempre que todos los argumentos sean del mismo tipo para el mapa. Si cambio la principal para usar una forma ligeramente más general:

tuple<int, float> t; 

t = map(square, 6, 8.0f); 

gcc 4.4 informes:

In function ‘int main(int, char**)’: 
error: no matching function for call to ‘map(<unresolved overloaded function type>, int, float)’ 

Alguna idea de cómo hacer este trabajo?

+3

¿Está 'abusing namespace std;'? ¿De dónde viene 'tuple'? –

+0

@KerrekSB: Dice que eliminó el 'uso de decs ', que me parece claro abuso de' uso '. –

Respuesta

5

Primero, no puede pasar una plantilla de función no resuelta como un puntero (o parámetro de plantilla), solo puede pasar instancias de ella. Lo que eso significa es que el primer argumento de su plantilla se pasa como int (*)(int) en este ejemplo, y no puede llamar a la instanciación float (*)(float). No estoy seguro de la mejor manera de solucionarlo, pero de todos modos no es técnicamente lo que preguntaste.

No tengo un compilador para probar esto, pero creo que si usa std::function para inferir los tipos que desea la función que está pasando, puede ser capaz de convertir los parámetros a la función. De esta manera:

template<typename T, typename Ts...> 
tuple<Ts...> map(std::function<T (T)> const &f, Ts... args) { 
    return make_tuple(static_cast<Ts>(f(static_cast<T>(args)))...); 
} 

Sede, creo que es necesario para emitir tanto el parámetro (como T) y el tipo de retorno (como Ts) para la función, ya que parece que algunas reglas de conversión implícitos no están funcionando dentro de este modelo.

Si mi sintaxis no funciona (probablemente no, ... s son complicados si no tienes un compilador para ellos), es posible que puedas reescribir esto como una función mucho más detallada que desempaqueta cada Ts antes de llamar a la función, y luego construye una tupla a medida que avanza. No estoy seguro si eso es realmente necesario, pero mi sensación es que el soporte del compilador para todo el desempaquetado de ... es un poco irregular en este momento, así que incluso si se te ocurre algo que debería funcionar, no me sorprendería si su compilador no pudo manejarlo.