Jak sobie radzicie z kodem ktory trzeba wykonac zawsze na koniec bloku? Zeby bylo mniej abstrakcyjnie zalozmy ze w funkcji wykorzystywana jest zmienna ktora zawsze na koniec musi byc inkrementowania. Opcje jakie widze:
- Klasyczne RAII - stworzyc osobna klase napisana specjalnie dla konkretnej sytuacji - wedlug mnie pozbawione sensu (zakladajac ze dla konkretnej potrzebnej sytuacji nikt jeszcze nie napisal odpowiedniej klasy).
- Kombinowac jak zrobic to samo ale nie wymagajac wolania zawsze na koniec. W tym konkretnym przykladzie inkrementacja mogla by byc na poczatku, a funkcja by operowala na dodatkowej zmiennej. Dla mnie zmiana dzialania programu zeby obejsc problemy jezyka jest jeszcze bardziej bez sensu. I raczej ciezko by cos takiego zrobic np. dla
fopen()
+fclose()
. - Recznie wolac kod wielokrotnie przy kazdym wyjsciu z bloku (czyli przed kazdym
return
i po wyjatku) - a to najgorsza z dotychczasowych opcji. - O dziwo w standardzie znam sposob w ktorym mozna to uzyskac. Zostalo to zaprojektowane do czego innego (choc tez mozliwe ze niekoniecznie. z dokumentacji: "Unlike std::unique_ptr, the deleter of std::shared_ptr is invoked even if the managed pointer is null." - po cos tak zrobili) i wyglada paskudnie, ale dziala:
std::shared_ptr<void> onExit(nullptr, [&](void*) {
processedCount++;
});
- Napisac klase podobnie jak w punkcie 1, ale uniwersalna, np:
struct OnExit {
OnExit(std::function<void()>&& func) : func(func) { }
~OnExit() {
func();
}
private:
const std::function<void()> func;
};
...
OnExit onExit([&] {
processedCount++;
});
- Klase powyzej mozna opakowac w makro (wiem ze wielu programistow ma alergie na makra, ale dla mnie jest to najlepsza z tych opcji) i wolac np. tak:
ON_EXIT(
processedCount++;
)
A moze znacie inne sposoby? A moze w standardzie jest cos rozsadniejszego niz shared_ptr
?
Ktoras z powyzszych opcji jest dla was nieakceptowalna bo jest "za brzydka" (a moze sa jakies inne powody)?