Reputation: 14032
Probably another dumb question that results from my studying in bad C++ book (I intend to correct this).
I was playing with sstream and tried the following function:
template <class num> num fromString(const std::string& str) {
std::istringstream ss(str);
num temp;
ss >> temp;
return temp;
}
When I call it like:
int i = fromString<int>("123");
it works ok. But if I call it like:
int i = fromString("123");
I got a compiling error:
error: no matching function for call to ‘fromString(std::string&)’
I thought the compiler would understand that if I'm assigning the value to a int
then I must be talking about fromString<int>
, but it seems it's not the case.
Am I missing something? Should I always specify the type of a templated function? Or just when the template type is the return type? Or just when the template type can't be determined by the types of the inputs?
Upvotes: 2
Views: 165
Reputation: 2102
You can get this effect with a simple trick.
#include <sstream>
#include <string>
using namespace std;
struct from_string {
string str;
from_string(const string& s) : str(s) { }
template <typename T>
operator T() const {
T ret;
stringstream ss(str);
ss >> ret;
return ret;
}
}
int main() {
string s("1234");
int a = from_string(s);
return 0;
}
Upvotes: 3
Reputation: 20656
In addition to what John said about this being what is called a 'non-deducible context', you can sometimes get around things like this by providing a dummy parameter of the template type:
#include <sstream>
#include <string>
template <typename T>
T from_string(const std::string& s, const T& /*dummy*/)
{
std::stringstream ss;
ss << s;
T t;
ss >> t;
return t;
}
int main()
{
std::string s = "23";
int i = from_string(s, i);
return 0;
}
That helps the compiler to deduce the type and avoids you having to explicitly specify it. It's particularly useful when the name of the variable is nice and short, as in the example above.
Upvotes: 1
Reputation: 101506
No, the compiler cannot deduce template parameters from return type alone. You have to be specific as you were originally:
int i = fromString<int>("123");
One of the reasons why the compiler cannot deduce in this case is because a number of types could be convertible to int
. For instance:
class Gizmo
{
public:
operator int() const;
};
How would the compiler know not to instantiate fromString<Gizmo>()
in this case?
Upvotes: 9