He escrito una clase de rasgos que me permite extraer información sobre los argumentos y el tipo de una función o objeto de función en C++ 0x (probado con gcc 4.5.0) . El caso general trata los objetos de función:Especializando una plantilla en una lambda en C++ 0x
template <typename F>
struct function_traits {
template <typename R, typename... A>
struct _internal { };
template <typename R, typename... A>
struct _internal<R (F::*)(A...)> {
// ...
};
typedef typename _internal<decltype(&F::operator())>::<<nested types go here>>;
};
Entonces tengo una especialización de las funciones de civil en el ámbito global:
template <typename R, typename... A>
struct function_traits<R (*)(A...)> {
// ...
};
Esto funciona bien, puedo pasar una función en la plantilla o un objeto de función y funciona correctamente:
template <typename F>
void foo(F f) {
typename function_traits<F>::whatever ...;
}
int f(int x) { ... }
foo(f);
¿Qué pasaría si, en lugar de pasar una función o un objeto función en foo
, quiero pasar una expresión lambda?
foo([](int x) { ... });
El problema aquí es que ni especialización de function_traits<>
aplica. El borrador de C++ 0x dice que el tipo de expresión es un "tipo de clase única, sin nombre, sin unión". Desenmascarar el resultado de llamar al typeid(...).name()
en la expresión me da lo que parece ser la convención de nomenclatura interna de gcc para el lambda, main::{lambda(int)#1}
, no es algo que sintácticamente represente un nombre de tipo C++.
En pocas palabras, ¿hay algo que pueda poner en la plantilla aquí:
template <typename R, typename... A>
struct function_traits<????> { ... }
que permitirá a esta clase rasgos para aceptar una expresión lambda?
No. ¿Por qué crees que necesitas algo como esto? – sellibitze
Creo que mi ejemplo dio un caso de uso decente: si tengo un algoritmo genérico que toma una función o objeto de función, puedo usar esta clase de rasgos para determinar no solo el tipo de retorno (que también podría hacerse con decltype hoy en día), sino también los tipos de los argumentos. (Dejé fuera la mayor parte del código para evitar que la publicación sea demasiado larga.) Dado que puedo pasar una función u objeto de función, para propósitos de ortogonalidad también me gustaría poder pasar una lambda. Esto es básicamente un ejercicio académico que surgió de la lectura de "Elementos de Programación". –
@Tony: La respuesta es sí, lo he hecho. Sin embargo, podré volver a esta pregunta un poco más tarde. ¿Qué rasgos estás tratando de obtener? – GManNickG