If you want or [...] the purpose of a template class.
The purpose of a template class is the generation of classes. If the OP needs a stable interface to several mechanically related classes, a template class is exactly what he needs to do the implementation.
O_o
You can do a lot with templates, but if you are going to do anything with these types, you'll eventually have to do the work.
If you don't want to do the work, or don't feel capable, you'll have to find an existing scripting library. (whiteflags provided a nice one.)
That said, templates will let you serialize and store the types safely and C++ already tracks the types of things if you let it. I'll give you a simple example. (Which is not up to my usual standard--example memory leaks.)
Soma
Code:
#include <iostream>
#include <iterator>
#include <map>
#include <sstream>
#include <stdexcept>
#include <string>
#include <typeinfo>
using namespace std;
struct variable_interface
{
virtual string get() const = 0;
virtual void set
(
const string & f
) = 0;
virtual istream & in
(
istream & f
) = 0;
virtual ostream & out
(
ostream & f
) const = 0;
virtual const type_info & type() const = 0;
};
template
<
typename type_F
>
struct variable: variable_interface
{
virtual string get() const
{
ostringstream v;
v << m;
return(v.str());
}
virtual void set
(
const string & f
)
{
istringstream v(f);
v.setf(ios::boolalpha);
type_F t;
if(!(v >> t))
{
throw(runtime_error("bad input"));
}
swap(m, t);
}
virtual istream & in
(
istream & f
)
{
return(f);
}
virtual ostream & out
(
ostream & f
) const
{
cout << m;
return(f);
}
virtual const type_info & type() const
{
return(typeid(type_F));
}
type_F m;
};
template <> struct variable<string>: variable_interface
{
virtual string get() const
{
ostringstream v;
v << m;
return(v.str());
}
virtual void set
(
const string & f
)
{
istringstream v(f);
string t;
if(!(getline(v, t)))
{
throw(runtime_error("bad input"));
}
swap(m, t);
}
virtual istream & in
(
istream & f
)
{
return(f);
}
virtual ostream & out
(
ostream & f
) const
{
cout << m;
return(f);
}
virtual const type_info & type() const
{
return(typeid(string));
}
string m;
};
istream & operator >>
(
istream & lhs_f,
variable_interface & rhs_f
)
{
return(rhs_f.in(lhs_f));
}
ostream & operator <<
(
ostream & lhs_f,
variable_interface & rhs_f
)
{
return(rhs_f.out(lhs_f));
}
int main()
{
string input;
map<string, variable_interface *> state;
while(getline(cin, input))
{
istringstream v(input);
string name;
string type;
string value;
v >> name;
v >> type;
getline(v, value);
if("bool" == type)
{
state[name] = new variable<bool>;
}
else if("float" == type)
{
state[name] = new variable<float>;
}
else if("string" == type)
{
state[name] = new variable<string>;
}
else
{
throw(runtime_error("bad input"));
}
state[name]->set(value);
}
const map<string, variable_interface *>::const_iterator begin(state.begin());
const map<string, variable_interface *>::const_iterator end(state.end());
for(map<string, variable_interface *>::const_iterator cursor(begin); end != cursor; ++cursor)
{
cout.setf(ios::boolalpha);
cout << cursor->first;
if(typeid(bool) == cursor->second->type())
{
cout << " as bool ";
}
else if(typeid(float) == cursor->second->type())
{
cout << " as float ";
}
else if(typeid(string) == cursor->second->type())
{
cout << " as string ";
}
else
{
cout << " as <unknown> ";
}
cout << *(cursor->second) << '\n';
}
return(0);
}