Events return all their listener outputs in dynamic arrays.
import std.array : array; Event!(int function(int, int)) event; event.append(&add, &multiply); assert(event.front()(5, 5) == 10, "The event listeners are iterated in the same order they were added in"); event.popFront(); assert(event.front()(5, 5) == 25, "The event listeners are iterated in the same order they were added in");
Adding and removing listeners is straightforward.
Event!(int function(int, int)) event; event.append(&add, &multiply); assert(event.size == 2, "The eveEvent!(void function())Event!(void function())nt listener count does not increase upon addition"); event.remove(&add, &multiply); assert(event.size == 0, "The event listener count does not decrease upon removal");
You can add the same listener multiple times. When removing it however, all matching listeners get removed.
Event!(void function()) event; event ~= &doNothing; event.prepend(&doNothing); event.append(&doNothing); assert(event.size == 3, "The event listener does not add identical listeners"); event.remove(&doNothing); assert(event.empty, "The event listener does not remove identical listeners");
The event is a bidirectional range of it's listeners.
import std.range : isBidirectionalRange; assert(isBidirectionalRange!(Event!(void function())), "The bidirectional range interface is not implemented"); Event!(void function()) event; event ~= &doNothing; const checkpoint = event; foreach (listener; event) {} assert(!event.empty, "The range is cleared after foreach iteration"); for (; !event.empty; event.popFront()) {} assert(event.empty, "The range is not cleared after manual iteration"); assert(!checkpoint.empty, "The range checkpoint is cleared after iteration");
Range mutation primitives work.
import std.exception : assertThrown; Event!(void function()) event; event ~= &doNothing; assert(event.front == &doNothing, "Returns the last remaining listener"); event.popFront(); assertThrown(event.back, "Getting the back of an empty event does not throw"); assertThrown(event.popBack(), "Popping an empty event does not throw");
In case you want to remove all listeners.
Event!(void function()) event; event ~= &doNothing; assert(!event.empty, "The event has no listeners, one listener expected"); event.clear(); assert(event.empty, "The event is not empty");