Die Frage ist streng genommen std::function
und nicht boost::function
. Weitere Details dazu finden Sie im Abschnitt Update am Ende dieser Frage, insbesondere den Teil, in dem es nicht möglich ist, nicht leere std::function
Objekte nach dem C++ 11-Standard zu vergleichen.std :: Funktion als Rückruf, ist die Abmeldung möglich?
Die C++ 11 std::function
Klassenvorlage ist für eine Sammlung von Rückrufen beibehalten wird. Man kann sie zum Beispiel in einem vector
speichern und bei Bedarf aufrufen. Es ist jedoch unmöglich, diese Objekte beizubehalten und die Aufhebung der Registrierung zuzulassen.
mich spezifisch sein lassen, sich vorstellen, diese Klasse:
class Invoker
{
public:
void Register(std::function<void()> f);
void Unregister(std::function<void()> f);
void InvokeAll();
private:
// Some container that holds the function objects passed to Register()
};
Beispielverwendungsszenario:
void foo()
{
}
int main()
{
std::function<void()> f1{foo};
std::function<void()> f2{[] {std::cout << "Hello\n";} };
Invoker inv;
// The easy part
// Register callbacks
inv.Register(f1);
inv.Register(f2);
// Invoke them
inv.InvokeAll();
// The seemingly impossible part. How can Unregister() be implemented to actually
// locate the correct object to unregister (i.e., remove from its container)?
inv.Unregister(f2);
inv.Unregister(f1);
}
Es ist ziemlich klar, wie die Register()
Funktion implementiert werden kann. Wie wäre es jedoch mit der Implementierung von Unregister()
? Nehmen wir an, dass der Container, der die Funktionsobjekte enthält, vector<std::function<void()>>
ist. Wie finden Sie ein bestimmtes Funktionsobjekt, das an den Aufruf Unregister()
übergeben wird? std::function
liefert eine überladene operator==
, die aber nur für ein leeres Funktionsobjekt testet (d. H. Es kann nicht zum Vergleichen zweier nicht leerer Funktionsobjekte verwendet werden, um zu sehen, ob beide auf denselben tatsächlichen Aufruf verweisen).
Ich würde mich über irgendwelche Ideen freuen.
Update:
Ideen bisher vor allem von der Zugabe eines Cookies bestehen zu jedem std::function
Objekt zugeordnet werden, die verwendet werden können, um es zu deregistrieren. Ich habe auf etwas gehofft, das für das Objekt selbst nicht exogen ist. Es scheint auch eine große Verwirrung zwischen std::function
und boost::function
zu geben. Die Frage ist streng genommen std::function
Objekte und nichtboost::function
Objekte.
Außerdem können Sie zwei nicht leere std::function
Objekte für die Gleichheit nicht vergleichen. Sie werden immer ungleiche nach dem Standard vergleichen. Also, Links in den Kommentaren zu Lösungen, die genau das tun (und boost::function
Objekte zum Booten verwenden) sind offensichtlich falsch im Zusammenhang mit dieser Frage.
Sie könnten tun, was MS mit Verbindungspunkten gemacht hat: Geben Sie einen Cookie (Index in Ihren Vektor) zurück, den der Anrufer für die Abmeldung bereitstellt. – WhozCraig
Ich speichere oft Schnittstellenzeiger als Callbacks und lege sie in einen Satz. Dann kann ich auf den Wert zugreifen, um die Registrierung aufzuheben. –
@RogerRowland nette Idee. – WhozCraig