Powiedzmy, że masz klasę foo
, która opakowuje kolekcję niektórych obiektów do wywołania. foo
ma funkcję składową run()
, która wykonuje iterację nad kolekcją i wywołuje każdy obiekt funkcji. foo
ma także członka remove(...)
, który usunie obiekt wywoływalny z kolekcji.W języku C++ istnieje idiomatyczny sposób ochrony przed sytuacją, w której uruchomienie zbioru działań powoduje zbieranie kolekcji?
Czy istnieje idiomatyczne, straż RAII stylu można umieścić w foo.run()
i foo.remove(...)
taki sposób, że usuwa, które były napędzane przez wywołanie foo.run()
zostanie odroczone do pożarów destructor strażnika? Czy można to zrobić za pomocą czegoś w standardowej bibliotece? Czy ten wzór ma nazwę?
Mój obecny kod wydaje się nieelegancki, dlatego szukam rozwiązania typu "najlepsza praktyka".
Uwaga: nie dotyczy to współbieżności. Rozwiązanie bez wątków jest w porządku. Kwestia dotyczy ponownego entrancy i samo-odniesienia.
Oto przykład problemu, nie ma nieeleganckiego "odsuń" strażnika.
class ActionPlayer
{
private:
std::vector<std::pair<int, std::function<void()>>> actions_;
public:
void addAction(int id, const std::function<void()>& action)
{
actions_.push_back({ id, action });
}
void removeAction(int id)
{
actions_.erase(
std::remove_if(
actions_.begin(),
actions_.end(),
[id](auto& p) { return p.first == id; }
),
actions_.end()
);
}
void run()
{
for (auto& item : actions_) {
item.second();
}
}
};
wtedy gdzie indziej:
...
ActionPlayer player;
player.addAction(1, []() {
std::cout << "Hello there" << std::endl;
});
player.addAction(42, [&player]() {
std::cout << "foobar" << std::endl;
player.removeAction(1);
});
player.run(); // boom
Edytuj ... w porządku to jak widzę to zrobić za pośrednictwem obiektu blokady RAII. Następujące powinny obsługiwać akcje wyrzucania i ponownego wejścia do wywołań w ramach działania, zakładając, że rekurencja zostanie ostatecznie zakończona (jeśli nie jest to wina użytkownika). Używałem buforowanych std :: functions, ponieważ w prawdziwej wersji tego kodu odpowiednik addAction i removeAction to funkcje szablonu, które nie mogą być przechowywane w jednorodnym opakowaniu waniliowym.
Dlaczego nie pokazać swoją "nieeleganckie 'odroczyć usuń' strażnika"? To brzmi jak sposób, w jaki podchodzę do tego. – 1201ProgramAlarm
Ponieważ mam to w moim prawdziwym kodzie, nie ta wersja zabawki i jest związana z prawdziwymi strukturami, które używają szablony variadic itp. To jest w pewnym sensie problem. Próbowałem znaleźć bardziej ogólne rozwiązanie, nie takie, które musi wiedzieć o wewnętrznych klasach podobnych do ActionPlayer. W każdym razie źle zaktualizuję ten przykład, gdy dostanę trochę czasu. – jwezorek