Signal provides a type-safe event system for connecting callbacks (slots) to events. When a signal is emitted, all connected slots are called with the provided arguments. This is commonly used for UI event handling.
Template Parameters
template <typename... Args>
class Signal
Types of arguments passed when the signal is emitted
Type Definitions
ConnectionID
using ConnectionID = size_t;
Unique identifier for signal connections. Used to disconnect specific callbacks.
SlotFunction
using SlotFunction = std::function<void(Args...)>;
Function type for signal slots. Must match the signal’s template parameters.
Methods
connect()
ConnectionID connect(SlotFunction slot)
Connects a callback function to the signal. The callback will be called when the signal is emitted.
Function to call when signal is emitted
Unique ID for this connection (use for disconnect)
Signal<int, std::string> mySignal;
auto id = mySignal.connect([](int value, const std::string& text) {
std::cout << "Received: " << value << ", " << text << std::endl;
});
emit()
void emit(Args... args) const
Emits the signal, calling all connected slots with the provided arguments.
Arguments to pass to all connected functions
mySignal.emit(42, "Hello"); // Calls all connected functions
disconnect()
void disconnect(ConnectionID id)
Disconnects a specific slot from the signal. The callback will no longer be called when the signal is emitted.
ConnectionID returned from connect()
auto id = mySignal.connect(callback);
mySignal.disconnect(id); // Remove the connection
Example Usage
Basic Signal
Signal<int, std::string> mySignal;
auto id = mySignal.connect([](int value, const std::string& text) {
std::cout << "Received: " << value << ", " << text << std::endl;
});
mySignal.emit(42, "Hello"); // Calls the connected function
mySignal.disconnect(id); // Remove the connection
class Button {
public:
Signal<> onClick; // No arguments
void handleClick() {
onClick.emit();
}
};
Button button;
button.onClick.connect([]() {
std::cout << "Button clicked!" << std::endl;
});
Multiple Connections
Signal<int> valueChanged;
auto id1 = valueChanged.connect([](int value) {
std::cout << "Handler 1: " << value << std::endl;
});
auto id2 = valueChanged.connect([](int value) {
std::cout << "Handler 2: " << value << std::endl;
});
valueChanged.emit(100); // Calls both handlers
valueChanged.disconnect(id1); // Remove first handler
valueChanged.emit(200); // Only calls second handler
Event Data
struct MouseEvent {
int x, y;
bool leftButton;
};
Signal<MouseEvent> onMouseClick;
onMouseClick.connect([](MouseEvent event) {
std::cout << "Clicked at (" << event.x << ", " << event.y << ")" << std::endl;
});
onMouseClick.emit({100, 50, true});
Common Patterns
button->onClick.connect([]() {
std::cout << "Button clicked!" << std::endl;
});
Value Changed Handler
slider->onValueChanged.connect([](float value) {
std::cout << "New value: " << value << std::endl;
});
Text Input Handler
textInput->onTextChanged.connect([](const std::string& text) {
std::cout << "Text changed to: " << text << std::endl;
});