2012-01-02 23 views
5

Mam fragment kodu:funkcje wewnętrzne czynienia ze zmiennymi z zakresu

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())); 

Oprócz iteratora przyrost magii, która nie może być zbyt obvoius tutaj bez uwag, chciałbym zdefiniować funkcja polegająca na zmniejszeniu duplikacji. Ale ponieważ użycie tej funkcji jest bardzo specyficzne, chciałbym uczynić ją funkcją lokalną. Idealnie:

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

W językach takich jak Python byłoby to całkowicie ok, ale jak to zrobić w C++?

EDIT:

To, co skończyło się, dzięki specjalnej @wilx a flaga -std=c++0x kompilator:

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++ nie pełnią funkcji zagnieżdżonych. Istnieje rozszerzenie w GCC, które pozwala na to, ale w standardzie C++ 11 istnieją funkcje lambda (http://en.wikipedia.org/wiki/C%2B%2B11#Lambda_functions_and_expressions), które mogą być używane zamiast. –

+1

Czy istnieje powód, aby użyć 'listy' zamiast' wektora'? Nie potrzebujesz hackowskich iteratorów, jeśli używałeś 'wektora'. Rozważ także użycie tylko "pary", jeśli listy mają zawsze dwa elementy. –

Odpowiedz

1

W tym przypadku proponuję przy użyciu przeciążenie jak angle2(std::list<Point> const &, etc.). Dwie proste argumenty są lepsze niż to, co masz teraz.

W C++ 11 można użyć lambd, które przechwytują swoje argumenty przez odniesienie.

Jeśli nie możesz użyć C++ 11 i masz ochotę na przygód, spróbuj Boost.Phoenix (część Boost.Spirit).

+0

'auto alpha = [& right, & left]() {return angle (...); }; std :: cout << alpha() * 180/M_PI << std :: endl; '- wydaje się działać. –

0

C++, o ile mi wiadomo, nie pozwala na to. Możesz ograniczyć zanieczyszczenie przestrzeni nazw stworzone przez dołączenie statycznego kwalifikatora na początku podpisu funkcji dla alfa, ale musisz go zdefiniować osobno.

Spowoduje to, że nazwa będzie używana tylko w tym pliku źródłowym. Możesz także zdefiniować makro wewnątrz funkcji, uważając, aby nie zdefiniować go, jeśli nie chcesz później dziwactwa preprocesora.

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

C++ nie obsługuje funkcji zagnieżdżonych, ale obejście może być wykonana z klas o zasięgu funkcyjnych:

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

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

Widzę, co masz na myśli, ale 'nestedFnc' nie może uzyskać dostępu do zmiennych zadeklarowanych w' scopeFnc', przynajmniej GCC na to skarży. Ale przynajmniej to rozwiązanie pomaga zmniejszyć zanieczyszczenie przestrzeni nazw; Mogę zrobić to za pomocą dwóch list jako argumentów. –

+0

@ wal-o-mat: Wystarczająco, jeśli naprawdę tego potrzebujesz, możesz zadeklarować potrzebne zmienne w Inner, ale przyznaję, że to nie sprawi, że twoja funkcja będzie czystsza. – stefaanv

Powiązane problemy