2012-01-02 14 views
5

tengo un fragmento de código como este:funciones internas que se ocupan de las variables del ámbito

std::list<boost::shared_ptr<Point> > left, right; 
// ... fill lists ... 

// now, calculate the angle between (right[0], right[1]) and (right[0], left[0]) 
double alpha = angle(*(right.begin()->get()), *(((++right.begin()))->get()), *(left.begin()->get())); 

std::cout << alpha * 180/M_PI << std::endl; 

if(alpha < 0){ 
    // do something with the lists, like reversing them. Especially the beginning and end of the lists may change in some way, but "left" and "right" are not reassigned. 
} 

// calculate the new alpha 
alpha = angle(*(right.begin()->get()), *(((++right.begin()))->get()), *(left.begin()->get())); 

Aparte de la magia de la subasta iterador que puede no ser demasiado obvoius aquí sin los comentarios, me gustaría definir una función double alpha() para reducir la duplicación. Pero debido a que el uso de esta función es muy específico, me gustaría que sea una función local. Lo ideal sería así:

int a, b; 
int sum(){ return a + b; } 
a = 5; b = 6; 
int s = sum(); // s = 11 
a = 3; 
s = sum(); // s = 9 now 

En lenguajes como Python esto sería perfectamente bien, pero ¿cómo hacer esto en C++?

EDIT:

Esto es lo que terminó con, especial gracias a @wilx y la bandera -std=c++0x compilador:

auto alpha = [&right, &left]() { 

    // not 100% correct due to my usage of boost::shared_ptr, but to get the idea 

    Point r_first = *(right.begin()); 
    Point l_first = *(left.begin()); 
    Point r_second = *(++right.begin()); 

    return angle(r_first, r_second, l_first); 
}; 


if(alpha() < 0) // fix it 

double new_alpha = alpha(); 
+4

C++ no tienen funciones anidadas. Sin embargo, hay una extensión en GCC que lo permite, y en el estándar C++ 11 hay [funciones lambda] (http://en.wikipedia.org/wiki/C%2B%2B11#Lambda_functions_and_expressions) que podrían usarse en lugar. –

+1

¿Hay alguna razón para usar una 'lista' en lugar de un' vector'? No necesitarías los incrementos de iterador hacky si usaras un 'vector'. Considere también usar solo un 'par 'si las listas siempre tienen dos elementos. –

Respuesta

1

En este caso se recomienda usar una sobrecarga como angle2(std::list<Point> const &, etc.). Dos argumentos simples son mejores que los que tienes ahora.

Con C++ 11 puede usar lambdas que capten sus argumentos por referencia.

Si no puedes usar C++ 11 y te sientes aventurero, prueba Boost.Phoenix (parte de Boost.Spirit).

+0

'auto alpha = [& right, & left]() {return angle (...); }; std :: cout << alpha() * 180/M_PI << std :: endl; '- parece hacer el truco. –

0

C++, por lo que yo sé, no lo permite. Puede limitar la contaminación del espacio de nombres creada al agregar el calificador estático al comienzo de la firma de la función para alfa, pero aún debe definirlo por separado.

Esto hará que el nombre se use solo dentro de ese archivo fuente. También podría definir una macro dentro de la función, teniendo cuidado de definirla si no desea la rareza del preprocesador más adelante.

int a, b; 
#define SUM() (a+b) 
int s=sum() 
#undef SUM 
2

C++ no soporta funciones anidadas, pero una solución puede ser hecho con clases de función restringidos:

void scopeFnc() 
{ 
    struct Inner 
    { 
    static int nestedFnc() { return 5; } 
    }; 

    int a = Inner::nestedFnc(); 
} 
+0

Veo lo que quiere decir, pero 'nestedFnc' no puede acceder a las variables declaradas en' scopeFnc', al menos GCC se queja de eso. Pero al menos esta solución ayuda a reducir la contaminación del espacio de nombres; Puedo hacerlo usando las dos listas como argumentos. –

+0

@ wal-o-mat: lo suficiente, si realmente lo necesitara, podría declarar las variables necesarias dentro de Inner, pero admito que eso no haría su función más limpia. – stefaanv

Cuestiones relacionadas