Type error in a template function
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 temp开发者_如何学运维lated 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?
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?
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;
}
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.
精彩评论