2013-03-09 45 views
2

我有一個Session類,它定義了多個採用不同參數的Send方法。例如:作爲參數傳遞的C++調用方法

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

實在是太多了複製,粘貼和理論上發送方法將在未來增長的數量。我想要更聰明的東西。

在理想情況下我想象一下,有模板廣播方法,它採用會話方法及其作爲參數的參數,即是這樣的:

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

和廣播呼叫將

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

問題是我不確定是否有可能以及如何實施廣播。我在思考std :: function和std :: bind,但仍然無法編譯我的代碼。

歡迎任何想法。

  • 修訂

它可能有2種相同的參數,但有不同的語義發送方法。例如:

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

我不明白你爲什麼不是重載發送方法? – 2013-03-09 15:12:12

+0

因爲可能有2個Send方法具有相同的參數但語義不同。例如SendName(const std :: string&name)和SendDescription(const std :: string&description) – 2013-03-09 15:18:03

+0

在你的例子中,你永遠不會說'sendName'和'sendDescription'你說'sendInt','send2Ints'等等......你做一個你永遠不應該做的手動名字mangaling。它的編譯器應該這樣做。 – 2013-03-09 15:19:42

回答

4

老實說將通過使用可變參數模板爲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; 

}; 

這裏是你將如何使用它:

​​

這裏是一個live example


UPDATE:

只要你真的不起超載,該解決方案能滿足您最初的要求:

#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

+0

感謝您的建議,但問題是2個發送方法可能採用相同的參數,但具有不同的語義。例如SendName(const std :: string&name)和SendDescription(const std :: string&description) – 2013-03-09 15:20:30

+0

@plamkata__:好的,讓我試着按照你的建議 – 2013-03-09 15:20:58

+0

@plamkata__:完成。請檢查更新的答案... – 2013-03-09 15:25:10

0

我不知道你真的想要達到什麼目的。它看起來像one SessionsManager have multiple Sessions。在SessionManager繼電器執行的行動,行動,所有的Session小號

,你必須將命令發送到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

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

謝謝。這也是一個很好的解決方案。 – 2013-03-09 15:56:18