You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在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 addListener allows the same function to be registered multiple times (matching your original code). If you want to avoid duplicates, uncomment the std::find check in addListener.
  • Parameter Support: The template works for void-return, no-argument functions as shown. To support delegates with parameters, use the commented-out variadic invoke method—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::mutex guard around all access to m_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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 08:06:14