I was wondering if it is possible to change the return type of a function based on the type of variable it is being assigned to. Here's a quick example of what I mean.
I want to create a function that parses a variable of int, bool, or float from a string. For example...
Int value = parse("37");
Float value = parse("3.14");
Bool value = parse("true");
I understand if I make this function a template, that the variable type must be determined from the argument list which is always going to be a string. Is there any other way of doing this with c++?
This can be done with a conversion function
struct proxy {
string str;
proxy(string const &str):str(str) { }
template<typename T> operator T() {
return boost::lexical_cast<T>(str);
}
};
proxy parse(string const &str) { return proxy(str); }
Now you just need to do
float a = parse("3.1");
And it should work well. Incidentally, you may just use the class directly. I recommend renaming it to conversion_proxy
to point to the fact that it's just a proxy to a happening conversion but that it itself doesn't do conversion
struct conversion_proxy {
string str;
conversion_proxy(string const &str):str(str) { }
template<typename T> operator T() {
return boost::lexical_cast<T>(str);
}
};
float a = conversion_proxy("3.1");
I can't tell from your question if you know this or not, but you can indeed do this with a template. The only catch is that you will have to specify the type that you are converting from in each invocation instead of relying on inference (since as you said the argument type will always be the same).
template<typename T> T parse(const string& str) { /* do stuff for other types */ }
template<> int parse<int>(const string& str) { /* do stuff for ints */ }
template<> double parse<double>(const string& str) { /* do stuff for doubles */ }
template<> bool parse<bool>(const string& str) { /* do stuff for bools */ }
// etc.
And then invoke as
int value = parse<int>("37");
double value = parse<double>("3.14");
bool value = parse<bool>("true");
If you already knew this just ignore this answer, but it's not clear from your question that you are aware that this is possible.
Of course, if what you're doing isn't really generic (and so you have to specialize for each type you want to parse) then writing a template isn't the right thing to do anyway.
By the way, you can do it pretty generically with a single function like this (assuming parse is what you really want to do):
#include <sstream>
template<typename T> T parse(const string& str)
{
T t;
std::istringstream sstr(str);
sstr >> t;
return t;
}
This will work for any default-constructable, stream-extractable type, which includes all built-ins.
You could pass your output argument as a pointer or reference.
Like this:
template<class T> void parse(const std::string &input, T& output);
Then code like this:
double d; parse(input, d);
int i; parse(input, i);
should work.
However, your code looks like a perfect fit for an std::istringstream that would just be:
istringstream is(input);
input >> d;
If you have somewhat complicated formatting involved, a trick I have had pretty good luck with involves creating custom objects with custom operator>> that pulls out data.
Then it could be like:
istringstring is(input);
input >> LineExtracter(x, y, d);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With