1a: No, types are not objects or values in C++ (as they are, for example, in Python). You can, however, use various values selected by the value of argv[1].
1b: Sorry, just can't do that.
2: dynamic_cast and typeid (both operators) are the only tools currently provided by the language to query type (not unusual, most languages have very few, but dedicated, tools for that), and using them solely to query type is often discouraged depending on situation (also not unusual among other languages).
2a: Yes, and as that is the simple, obvious, and works here—there's no reason to use anything else, but as it's example code, let's assume you need a different solution. You could call a function template instantiated on the right type, but as this is pretty much the same thing as the rest of 2a, I don't go into it.
2b: Example using a subclass template, just because it's handy:
struct Base {
virtual ~Base() {}
friend std::ostream& operator<<(std::ostream& s, Base const& v) {
v._print(s);
return s;
}
private:
virtual void _print(std::ostream&) const = 0;
};
template<class T>
struct Value : Base {
T data;
explicit
Value(T const& data) : data(data) {}
private:
virtual void _print(std::ostream& s) const {
s << data;
}
};
Use:
int main(int argc, char** argv) {
using namespace std;
auto_ptr<Base> p;
string const type = argc > 1 ? argv[1] : "int";
if (type == "int") {
p.reset(new Value<int>(2));
}
else if (type == "float") {
p.reset(new Value<double>(2.2));
}
cout << *p << '
';
return 0;
}
This is starting to merge the two types into one type, and they both present the same interface, Base, here. However, this doesn't lend itself well to every solution, and a variant such as boost.variant can be better, particularly when the various types required are small in number and known well in advance.