procedimientos - ¿C++ 11 tiene soporte para funciones locales?
funciones y procedimientos en c++ (5)
Ahora que hay lambdas en C ++, parece realmente tonto que no pueda declarar una función local ...
p.ej:
Puedo declarar un tipo en el cuerpo de una función, incluso inicializarlo como una tabla de valores. Pero no puedo crear una función auxiliar que funcione con ese tipo de datos, porque no puedo declarar una función en una función y no puedo referirme a ese tipo de datos fuera de la función porque solo está disponible en ese ámbito.
Hay ocasiones en las que es bastante sencillo extraer el tipo de datos de la función y definir mi tipo de datos y las funciones de ayuda allí (alcance del archivo local), pero hay ocasiones en las que no es realmente una solución plausible, por ejemplo, al inicializar la tabla con lambdas en línea que se refieren a las variables de alcance local (o esto).
¿Alguna idea de si el soporte para funciones locales viene, ya está definido, o por qué es difícil de implementar para los compiladores y, por lo tanto, no son parte del estándar?
Es bastante complicado, pero puede crear una función local dentro de un tipo de estructura local:
int quadruple(int x) {
struct Local {
static int twice(int val) { return val * 2; }
};
return Local::twice(Local::twice(x));
}
Tenga en cuenta que la función local no tiene acceso a las variables locales, para eso necesitaría un lambda. Sin embargo, puede ser útil para sobrecargas locales:
template <typename T>
T mod(T x, T y) {
struct Local {
static int local(int x, int y) { return x % y; }
static double local(double x, double y) { return std::fmod(x, y); }
};
return Local::local(x, y);
}
Las funciones locales definitivamente no son difíciles de implementar, estuvieron presentes al menos en 1968 en Pascal, tal vez incluso antes. Se implementan como una extensión C en GCC.
Pasar la dirección de una función anidada es un poco más complicado, generalmente incluye configurar un fragmento de código (trampolín), que primero configura el enlace estático / pantalla / cualquier mecanismo que se use para acceder a las variables locales y luego ejecuta el código de función real . El trampolín reside en la pila, lo que significa que la pila debe ser ejecutable, con las implicaciones de seguridad habituales de esto.
Cualquiera que el comité de C ++ haya considerado y rechazado las funciones anidadas es una suposición, pero sugeriría que, si bien no es tan difícil de implementar, los beneficios de las funciones anidadas no valen realmente la pena.
No hay funciones locales en C ++ 11.
Pero hay lambdas.
¡Y tu tipo local puede tener funciones de miembro!
No hay funciones locales, pero no son tan útiles sin el cierre, es decir, el acceso a las variables locales. En cualquier caso, puede emular una función local con un lambda bastante fácil.
En lugar de:
void foo(int x)
{
struct S
{
//...
};
int Twice(int n, S *s) //Not allowed
{
return 2*n;
}
S s;
int x = Twice(3, &s);
//...
}
Hacer:
void foo()
{
struct S
{
//...
};
auto Twice = [](int x, S *s) -> int //Cool!
{
return 2*x;
}; //Twice is actually a variable, so don''t forget the ;
S s;
int x = Twice(3, &s);
//...
}
Si el conjunto de captura está vacío, ( []
) incluso se puede convertir en un puntero a función ordinario, ¡igual que uno real!
Y AFAIK, los lambdas pueden usar tipos locales sin problemas. Pero, por supuesto, las funciones miembro públicas estáticas en esa estructura también deberían funcionar bien.
Y como nota adicional, relacionada indirectamente con su pregunta, lo que está permitido en C ++ 11 es crear una instancia de una plantilla usando un tipo local (que estaba prohibido en C ++ 98):
void foo()
{
struct S {};
std::vector<S> vs; //error in C++98, ok in C++11
}
No, no puede hacer esto, pero seguramente las lambdas son más útiles que las funciones locales puras, ya que también pueden capturar el estado opcionalmente. Se pueden usar de forma anónima o asignarse a una variable automática y usarse en tantos lugares como desee.
Anteriormente, la otra solución principal (especialmente cuando se utilizan los algoritmos de biblioteca estándar) era definir una estructura de functor local con una implementación de operador () adecuada. También puede capturar el estado utilizando este método, pero requiere más código para hacerlo. Las Lambdas son una forma muy clara y concisa de lograr lo mismo.