作为参数传递的 C++ 调用方法

标签 c++ function templates c++11 bind

我有一个 Session 类,它定义了多个采用不同参数的 Send 方法。例如:

class Session
{
public:
    void SendInt(int i);
    void SendTwoInts(int i1, int i2);
    void SendStringAndInt(const std::string& str, int i);
};

我还有 SessionsManager 类来保存所有 session 。

class SessionsManager
{
private:
    std::vector<Session*> m_Sessions;
    ...
};

我想向 SessionsManager 类添加广播方法,该类为每个 session 调用相同的方法。如果我只是为每个 session 发送方法定义一个单独的广播方法,我将像这样结束:

class SessionsManager
{
public:
     void BroadcastInt(int i) { for(auto it : m_Sessions) { it->SendInt(i); } };
     void BroadcastTwoInts(int i1, int i2) { for(auto it : m_Sessions) { it->SendTwoInts(i1, i2); } };
...
};

复制粘贴太多了,理论上 Send 方法的数量将来会增加。我想要更聪明的东西。

在完美的场景中,我想象有一个模板化的 Broadcast 方法,它将 Session 方法及其参数作为参数,即类似:

template<typename Method, typename ...Args)
void Broadcast(Method, Args ... args)
{
...
}

广播调用将是

Broadcast(&Session::SendInt, 2);
Broadcast(&Session::SendTwoInts, 2, 3);

问题是我不确定是否可能以及如何准确地实现广播。我正在考虑 std::function 和 std::bind 但仍然无法编译我的代码。

欢迎任何想法。

  • 已更新

可以有 2 个具有相同参数但语义不同的 Send 方法。例如:

void SendName(const std::string& name);
void SendDescription(const std::string& description);

最佳答案

老实说,我会通过使用 Broadcast 的可变参数模板来解决这个问题,并简单地为不同的参数重载 Send() 方法。

这是代码:

#include <vector>
#include <string>

class Session
{
public:

    void Send(int i) { }
    void Send(int i1, int i2) { }
    void Send(const std::string& str, int i) { }
};

class SessionsManager
{

public:

    template<typename... Args>
    void Broadcast(Args&&... args)
    {
        for(auto it : m_Sessions)
        {
            it->Send(std::forward<Args>(args)...);
        }
    }

private:

     std::vector<Session*> m_Sessions;

};

以下是如何使用它:

int main()
{
    SessionsManager sm;
    sm.Broadcast(1, 2);
    sm.Broadcast(1);
    sm.Broadcast("Hello", 2);
}

这是一个 live example .


更新:

如果您确实无法承受重载,此解决方案可以满足您最初的要求:

#include <vector>
#include <string>

class Session
{
public:

    void SendInt(int i) { }
    void SendTwoInts(int i1, int i2) { }
    void SendStringAndInt(const std::string& str, int i) { }
};

class SessionsManager
{
public:

    template<typename M, typename... Args>
    void Broadcast(M m, Args&&... args)
    {
        for(auto it : m_Sessions)
        {
            ((*it).*m)(std::forward<Args>(args)...);
        }
    }

private:

     std::vector<Session*> m_Sessions; // You could use shared_ptr<> here

};

这就是你如何使用它:

int main()
{
    SessionsManager sm;
    sm.Broadcast(&Session::SendTwoInts, 1, 2);
    sm.Broadcast(&Session::SendInt, 1);
    sm.Broadcast(&Session::SendStringAndInt, "Hello", 1);
}

这是一个 live example .

关于作为参数传递的 C++ 调用方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15312209/

相关文章:

c++ - 使用 ENet 从 Cereal 发送二进制数据的 StringStream

带参数的 Python 函数不起作用

c++ - 如何避免简单的递归模板类型定义

c++ - 为什么 static const char * template struct 成员没有初始化

c++ - 用 C++ 设计前端/后端系统?

c++ - 当函数模板专门用于不同的命名空间时,GCC 和 clang 不同意

c++ - 树突变和共享指针问题的访问者模式

Python selenium 将屏幕截图保存在新创建的文件夹中

r - 如何避免在函数中重复代码以使用ggplot2绘制密度直方图和简单直方图?

c++ - 默认模板参数在(部分特化的)类模板的重载决议中的作用