2

異なる引数を取る複数の Send メソッドを定義する Session クラスがあります。例えば:

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 クラスに追加したいと思います。Session Send メソッドごとに個別のブロードキャスト メソッドを定義するだけの場合、次のように終了します。

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 メソッドの数は将来増えるでしょう。もっと賢いものが欲しい。

完璧なシナリオでは、Session メソッドとその引数を引数として取るテンプレート化された Broadcast メソッドがあると想像します。つまり、次のようなものです。

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

3 に答える 3

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;

};

使用方法は次のとおりです。

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

そして、これがライブの例です。

于 2013-03-09T15:17:49.067 に答える
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);
}
于 2013-03-09T15:53:20.233 に答える
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

于 2013-03-09T15:27:01.267 に答える