簡體   English   中英

作為參數傳遞的C ++調用方法

[英]C++ call method passed as argument

我有一個Session類,定義了多個采用不同參數的Send方法。 例如:

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

我也擁有保存所有會話的SessionsManager類。

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

我想向每個會話調用相同方法的SessionsManager類添加廣播方法。 如果我僅為每個會話發送方法定義一個單獨的廣播方法,我將結束:

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);
}

這是一個生動的例子


更新:

如果您真的負擔不起過載,那么此解決方案可以滿足您的原始要求:

#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);
}

這是一個生動的例子

使用std::bind解決方案可能看起來像

#include <iostream> 
#include <functional> 
#include <vector> 

class Session
{
public:
    void SendInt(int i){ std::cout << i; }
    void SendTwoInts(int i1, int i2){ std::cout << i1;}
};

class SessionsManager
{
public:
   std::vector<Session*> m_Sessions;
    template<typename T, typename ...Args>
    void Broadcast(T f, Args&& ...args) {
        for (auto it : m_Sessions) {
            std::bind(f, it, std::forward<Args>(args)...)();
        }
    }
};


int main() {
   SessionsManager m;
   m.m_Sessions.push_back(new Session());
   m.m_Sessions.push_back(new Session());
   m.Broadcast(&Session::SendInt, 2);
   m.Broadcast(&Session::SendTwoInts, 3, 2);
}

我不知道您到底要達到什么目標。 看起來one SessionsManager have multiple Sessions SessionManager上執行操作會將該操作中繼到其所有Session

並且您有一個將命令發送到SessionManager的廣播SessionManager

struct SessionManager{
   template <typename F>
   void broadcast(F f){
     std::for_each(m_sessions.begin(), m_sessions.end(), f);
   }

   std::vector<Session*> m_sessions;
};

現在,您進行boost::bind並將其發送到SessionManager::broadcast

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM