在C++中实现Signal模板的技术咨询(附代码片段)
Implementing a C++ Signal Template
Let’s complete your Signal template to support core functionality like adding listeners, invoking callbacks, and managing registered functions, plus add some useful extras for flexibility.
Step 1: Full Signal Template Implementation (Signal.h)
Here’s a robust, reusable implementation that matches your initial code structure:
#ifndef SIGNAL_H #define SIGNAL_H #include <vector> #include <algorithm> template <typename DelegateType> class Signal { private: std::vector<DelegateType> m_listeners; public: // Add a listener to the signal (allows duplicates by default) void addListener(DelegateType listener) { m_listeners.push_back(listener); // Uncomment below to block duplicate listeners // if (std::find(m_listeners.begin(), m_listeners.end(), listener) == m_listeners.end()) { // m_listeners.push_back(listener); // } } // Remove a specific listener from the signal void removeListener(DelegateType listener) { auto it = std::find(m_listeners.begin(), m_listeners.end(), listener); if (it != m_listeners.end()) { m_listeners.erase(it); } } // Clear all registered listeners void clearListeners() { m_listeners.clear(); } // Invoke all registered listeners (for no-argument delegates) void invoke() { for (auto listener : m_listeners) { listener(); } } // Optional: Variadic version for delegates with parameters // template <typename... Args> // void invoke(Args&&... args) { // for (auto listener : m_listeners) { // listener(std::forward<Args>(args)...); // } // } }; #endif // SIGNAL_H
Step 2: Updated Main.cpp with Full Functionality
Extend your test code to try out all the Signal’s features:
// Developed by Trofimov Yaroslav on 02.04.18 #include <iostream> #include "Signal.h" void f1() { std::cout << "here in f1" << std::endl; } void f2() { std::cout << "F2 F2 F2" << std::endl; } typedef void (* VoidResultDelegate)(); int main(void) { Signal<VoidResultDelegate> signalVoid; // Add listeners (including duplicate f1) signalVoid.addListener(f1); signalVoid.addListener(f1); signalVoid.addListener(f2); std::cout << "First invoke (3 listeners):" << std::endl; signalVoid.invoke(); // Remove one instance of f1 signalVoid.removeListener(f1); std::cout << "\nSecond invoke (2 listeners):" << std::endl; signalVoid.invoke(); // Clear all listeners signalVoid.clearListeners(); std::cout << "\nThird invoke (no listeners):" << std::endl; signalVoid.invoke(); return 0; }
Key Details & Enhancements
- Duplicate Handling: The default
addListenerallows the same function to be registered multiple times (matching your original code). If you want to avoid duplicates, uncomment thestd::findcheck inaddListener. - Parameter Support: The template works for void-return, no-argument functions as shown. To support delegates with parameters, use the commented-out variadic
invokemethod—this lets you pass arguments to all listeners. - Lambda & Functor Support: For more flexibility (like using lambdas), replace the raw function pointer delegate with
std::function<void()>as the template parameter. This will let you register any callable type. - Thread Safety: This implementation isn’t thread-safe. If you need multi-threaded use, add a
std::mutexguard around all access tom_listeners.
Example Output
Running the updated code will produce:
First invoke (3 listeners): here in f1 here in f1 F2 F2 F2 Second invoke (2 listeners): here in f1 F2 F2 F2 Third invoke (no listeners):
内容的提问来源于stack exchange,提问作者ggghahaha
相关产品推荐
相关产品推荐

