2012-02-24 23 views
10

Vamos, que tenemos una funcion plantilla:¿Es posible pasar una plantilla de función como argumento de plantilla? asssume

template<typename T1, typename T2, typename T3> 
T3 such_fun(T1 a, T2 b) { 
    // do something... 
} 

y ahora queremos utilizarlo como un argumento en otra plantilla, por ejemplo, como ese

template<typename T1, template<typename, typename, typename> some_function> 
void big_fun(T1 a) { 
    // some code... 
    a = some_function<T1, T1, T1>(a, a); 
    // some code... 
} 

¿Es posible?

Sé que puedo usar una estructura con el operador defined(). Solo tengo curiosidad acerca de las funciones.

EDIT:

Mientras estaba escribiendo esa pregunta mi amigo encontró una solución parcial:

template<typename T1, T1 (*some_function)(T1, T1)> 
void big_fun(T1 a) { 
    // some code... 
    a = some_function(a, a); 
    // some code... 
} 

Pero aún así - Soy curioso si es posible sin una materialización de un tipo de función antes llamada. Por ejemplo, es posible que desee llamar a la plantilla pasada con varias combinaciones de tipos:

template<typename T1, typename T2, template<typename, typename, typename> some_function> 
void big_fun(T1 a, T2 b) { 
    // some code... 
    a = some_function<T1, T1, T1>(a, a); 
    a = some_function<T1, T2, T1>(a, b); 
    b = some_function<T2, T2, T2>(b, b); 
    b = some_function<T2, T1, T2>(b, a); 
    // some code... 
} 

Respuesta

8

No, esto no es posible. De 14.3.3 en el N3337:

Una plantilla-argumento a favor de una plantilla-parámetro de plantilla será el nombre de una plantilla de clase o de una plantilla de alias, expresado como id-expresión. Cuando el argumento de la plantilla nombra una plantilla de clase, , solo se consideran las plantillas de clases primarias al hacer coincidir el argumento de la plantilla con el parámetro correspondiente; las especializaciones parciales no se consideran incluso si sus listas de parámetros coinciden con el del parámetro plantilla de plantilla.

El primer párrafo solo menciona explícitamente plantillas de clase. Supongo que tampoco vale la pena, ya que puedes hacer algo muy similar con funciones o un std::function como argumento.

+1

No entiendo ni una palabra de lo que dices ... -1, ¿puedes darnos una ilustración que no sea fluida en standarese? – lurscher

+0

@lurscher porque _no_ entiendes que es una razón horrible para rechazarlo. No renuncio a los físicos cuánticos cuando hablan de física cuántica porque no lo entiendo. –

+0

@SethCarnegie, no estoy de acuerdo. Creo que es, en sí mismo, una muy buena razón. además, la respuesta es incorrecta también; lo que la pregunta quiere hacer es completamente posible, incluso en C++ 03.Creo que hay una desconexión entre lo que el SO pide y lo que contesta el pmr, de ahí el voto a la baja. Si mejora su respuesta, estaré más que feliz de retirarla. – lurscher

1

Las plantillas en C++ se compilan durante el tiempo de compilación utilizando los tipos concretos. Ellos deben ser conocidos.

Esto dice que puede ir un poco más allá con su solución parcial al pasar una plantilla de función cuyos argumentos se pueden deducir. Tenga en cuenta que esto no es diferente a la función de pasar explícitamente con tipos concretos, solo tiene que escribir menos.

template<typename T> 
T square(T a, T b) 
{ 
    return a * b; 
} 

template<typename T, T (*some_function)(T, T)> 
T test(T a) 
{ 
    return square (a, a); 
} 

void main() 
{ 
    int a = test<int, square>(2); 
    float b = test<float, square>(2.2f); 
} 
+0

? Realmente no veo una diferencia entre ese código y el código de "solución parcial". El problema es que en este enfoque es imposible usar 'some_function' con varios tipos sin agregar explícitamente un nuevo argumento de plantilla. Y tengo curiosidad si hay una manera más flexible (pero aún sin uso de clase). –

0

Mientras template< typename T1, typename T2, typename T3> someTemplate evalúa en cierta clase real y sin errores que se puede utilizar la mayor cantidad de combinaciones que desee, y dentro de otras plantillas.

¿Has intentado compilarlo? Muéstranos qué error obtienes (y muestra concreta)

+0

Sé que puedo usar una clase. Lo escribí en mi publicación. La pregunta es sobre funciones comunes. Pero de acuerdo con lo que @pmr escribió, parece sintácticamente imposible. –

+1

La sintaxis que usa el OP (y por extensión) no es válida. El correcto es 'template class someTemplate'. Además, nada aquí se trata de 'evaluación'. Imagínelo de esta manera: un argumento de plantilla de plantilla solo puede coincidir con el nombre de una plantilla de clase que tenga la misma lista de parámetros de plantilla (esto es importante para los argumentos de plantilla sin tipo). Este nombre de plantilla se inyecta en la otra plantilla y se puede crear una instancia allí. El problema es 'plantilla de clase'. No veo una razón específica para esta restricción, pero tampoco pertenezco al comité ni a un abogado de idiomas. – pmr

+0

@pmr Uhm. Bien. La sintaxis que utilicé en un ejemplo era parcialmente un pseudocódigo, es decir, sabía que no podía usar una palabra clave 'class', así que no usé ninguna. Fue sobre la idea. –

Cuestiones relacionadas