我有一个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类添加广播方法,为每个会话调用相同的方法。如果我只为每个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); } };
...
};
复制粘贴太多,理论上发送方法的数量将来会增长。我想要更聪明的东西。
在完美的场景中,我想象有模板化的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);
答案 0 :(得分: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);
}
这是一个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。
答案 1 :(得分: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);
}
答案 2 :(得分:0)
我不知道你到底想要做什么。它看起来像one SessionsManager have multiple Sessions
。对SessionManager
执行操作会将对该Session
s
你有一个广播员向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