可能是我在恶劣的C ++书籍中学习的另一个愚蠢的问题(我打算纠正这个问题)。
我正在使用sstream并尝试以下功能:
template <class num> num fromString(const std::string& str) {
std::istringstream ss(str);
num temp;
ss >> temp;
return temp;
}
我称之为:
int i = fromString<int>("123");
它运作正常。但如果我称之为:
int i = fromString("123");
我收到了编译错误:
error: no matching function for call to ‘fromString(std::string&)’
我认为编译器会理解,如果我将值赋给int
,那么我必须谈论fromString<int>
,但似乎并非如此。
我错过了什么吗?我应该总是指定模板化函数的类型吗?或者只是模板类型是返回类型?或者只是当模板类型无法通过输入类型确定时?
答案 0 :(得分:9)
不,编译器不能单独从返回类型推断出模板参数。你必须像你原来那样具体:
int i = fromString<int>("123");
在这种情况下编译器无法推断的原因之一是因为许多类型可以转换为int
。例如:
class Gizmo
{
public:
operator int() const;
};
在这种情况下,编译器如何知道不实例化fromString<Gizmo>()
?
答案 1 :(得分:3)
你可以通过简单的技巧获得这种效果。
#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;
}
答案 2 :(得分:1)
除了约翰所说的这就是所谓的“不可推导的上下文”之外,你有时可以通过提供模板类型的虚拟参数来解决这个问题:
#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;
}
这有助于编译器推断出类型并避免必须明确指定它。当变量的名称很好而且很短时,它就特别有用,如上例所示。