1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
| #include <string>
#include <map>
#include <iostream>
#include <sstream>
#include <memory>
class CmdFunction //! Class abstraite contenant une commande
{
//Non copyable
CmdFunction(CmdFunction const&);
CmdFunction& operator =(CmdFunction const&);
public:
CmdFunction(){}
virtual ~CmdFunction() = 0 {};
};
template<typename S>
class CmdFunctionForType : public CmdFunction //! Class abstraite contenant est specialisé pour un type de flux
{
public:
virtual void exec(S& iss) = 0;
};
class LineCommander
{
public:
void registerCommand(const std::string &com, std::shared_ptr<CmdFunction> handler)
{
m_coms[com] = handler;
}
void unregisterCommand(const std::string &com)
{
m_coms.erase(com);
}
template<typename S>
void exec(const std::string &com, S &istr)
{
//! On recupere l'iterateur
auto iter = m_coms.find(com);
if(iter == m_coms.end())
return; //retour ou erreur
CmdFunction& handler = *iter->second;
//! On downcast dans le type template CmdFunctionForType aproprié
//! Si ca echoue, c'est que c'est le mauvais type de flux.
//! Ca lancera un bad_cast.
CmdFunctionForType<S>& downcastedHandler =
dynamic_cast<CmdFunctionForType<S>&>(handler);
downcastedHandler.exec(istr);
}
private:
std::map<std::string, std::shared_ptr<CmdFunction> > m_coms;
};
int main()
{
LineCommander m_lc;
//! Specialisation pour le comportement voulue.
//! Ok c'est un peut plus compliqué qu'un lambda, mais ca va encore.
//! Remarque, on peut passer des argument dans le constructeur, équivalent a
//! la liste de capture dans les lambda.
class LocalCmdFunctionForIstream : public CmdFunctionForType<std::istream>
{
public:
void exec(std::istream& iss)
{
unsigned int ip = 0;
unsigned int port = 0;
iss >> ip;
iss >> port;
//accept(ip, port);
std::cout << ip << " " << port << std::endl;
}
};
m_lc.registerCommand("accept", std::make_shared<LocalCmdFunctionForIstream>());
std::stringstream iss("859212563 48496");
m_lc.exec<std::istream>("accept", iss); //Attention, ici, il faut specifier le bon type
return EXIT_SUCCESS;
} |
Partager