#include <string>
#include <vector>
#include <map>
#include <assert.h>
#include <iostream>
using namespace std;
class Variant{
public:
enum Type{
INT,
FLOAT,
STRING
};
Variant(int i){
m_type = INT;
m_int = i;
}
Variant(float f){
m_type = FLOAT;
m_float = f;
}
Variant(const string &s){
m_type = STRING;
m_string = s;
}
Type m_type;
int m_int;
float m_float;
string m_string;
};
class ArgList{
public:
template<class T>
ArgList(const T &val){
m_args.emplace_back(val);
}
template<class HEAD, class... TAIL>
ArgList(const HEAD &head,const TAIL&... tail){
m_args.emplace_back(head);
ArgList t(tail...);
m_args.insert(m_args.end(),t.m_args.begin(),t.m_args.end());
}
vector<Variant> m_args;
};
class ICommand{
public:
virtual void execute(const ArgList& args) = 0;
template<class... ARGS>
void executeList(const ARGS &... args){
execute(ArgList(args...));
}
};
class Add : public ICommand{
public:
virtual void execute(const ArgList& args){
assert(args.m_args.size() == 2);
assert(args.m_args[0].m_type == Variant::INT);
assert(args.m_args[1].m_type == Variant::INT);
cout << "Add result:" << args.m_args[0].m_int + args.m_args[1].m_int << endl;
}
};
class Negate : public ICommand{
public:
virtual void execute(const ArgList& args){
assert(args.m_args.size() == 1);
assert(args.m_args[0].m_type == Variant::INT);
cout << "Negate result:" << -args.m_args[0].m_int<< endl;
}
};
class Print : public ICommand{
virtual void execute(const ArgList& args){
for(auto &var : args.m_args){
switch(var.m_type){
case Variant::INT:
cout << "int " << var.m_int << ",";
break;
case Variant::FLOAT:
cout << "float " << var.m_float << ",";
break;
case Variant::STRING:
cout << "string " << var.m_string << ",";
break;
}
}
cout << endl;
}
};
int main(){
map<string,ICommand*> commands;
commands["Add"] = new Add();
commands["Negate"] = new Negate();
commands["Print"] = new Print();
commands["Add"]->executeList(1,2);
commands["Negate"]->executeList(4);
commands["Print"]->executeList(1,2.0f,"helloworld!");
}