我正在尝试编写一个简单的函数,它将从一个范围内的用户输入中获取一个数字。
当实现此功能时,我明确地告诉它我希望它与int
实例化,但我仍然得到错误:
thermo.cpp:105:31: error: no matching function for call to ‘getInput(int&)’
为什么试图找到一个以int&
为参数的函数?
template<class T, T min = std::numeric_limits<T>::min, T max = std::numeric_limits<T>::max>
T getInput(T default_value = T()){
std::string input;
T myNumber = T(); //default inits
while(true){
getline(cin, input);
if(input.length() == 0){
return default_value;
}
// This code converts from string to number safely.
stringstream myStream(input);
if (myStream >> myNumber){
if(myNumber > max || myNumber < min){
stringstream ss;
ss << "Input out of bounds. Received " << myNumber << " expected between " << min << " and " << max << ".";
throw invalid_argument(ss.str());
}
return myNumber;
}
cout << "Invalid number, please try again" << endl;
}
}
void get(const std::string& prompt, int& param){
cout << prompt << " [" << param << "]:";
param = getInput<int,0>(param); // i specifically tell it i want 'int', why am i getting 'int&'?
}
更新
如果我试试CharlesB的建议:
void get(const std::string& prompt, int& param){
cout << prompt << " [" << param << "]:";
param = getInput<int,0>(int(param));
}
我得到了
thermo.cpp:105:36:错误:没有匹配函数来调用'getInput(int)'
忘记:
gg 4.5.3在cygwin下
命令行:
$ g ++ thermo.cpp -o thermo.exe -Wall -pedantic -std = c ++ 0x
更新2
如果我这样称呼它
void get(const std::string& prompt, int& param){
cout << prompt << " [" << param << "]:";
param = getInput<int,0,15>(int(param)); // fully parameterized
}
它有效...但我不想在每次调用时指定上限(甚至不是numeric_limits
)。
答案 0 :(得分:3)
请勿使用min
和max
的模板:
template<class T>
T getInput(T default_value = T(), T min = std::numeric_limits<T>::min(), T max = std::numeric_limits<T>::max());
没有理由为这些参数使用模板(除了它不起作用的事实)。
编辑:您不能将这些参数用作模板值,因为std::numeric_limits<T>::min()
是一个函数,它的值在运行时是已知的,并且模板值参数必须绑定到一个值在编译时。这是有效的:
template<class T, T min = 0, T max = 5>
T getInput(T default_value);
由于0和5在编译期间是已知的。
答案 1 :(得分:2)
我不知道这是否是 问题,但我无法想象这有什么帮助。这一行:
template<class T, T min = std::numeric_limits<T>::min, T max = std::numeric_limits<T>::max>
...将min / max用作值when they're really functions。也许这会让模板参数混淆不清?
答案 2 :(得分:2)
错误代码并不代表您的想法。错误代码是:
的简写 没有匹配函数调用getInput
,它将int
可修改的左值表达式作为单个参数
其中 int
可修改的左值表达式是您在此案例param
中用于进行调用的表达式的类型。现在问题是这种格式的错误代码输出是非常冗长的,只用两个或三个非平凡类型的参数就很难读取,所以编译器会压缩错误报告并告诉你:
没有对getInput(int&)
的匹配函数调用,请注意这里int&
不是将要调用的函数的类型,因为编译器无法找到这样的函数函数,而是它在调用中使用的参数的类型。
如果您执行CharlesB建议的更改,那么您将收到一条不同的错误消息,指出它无法找到getInput(int)
。这里的区别在于int(param)
创建了一个临时( rvalue表达式),因此错误现在反映了它。需要一个不同的错误代码来自这样一个事实:如果你有getInput(int&)
函数,在第二种情况下,不能使用该重载。
关于您收到该错误代码的原因,基本问题是std::numeric_limits<T>::max
不是T
类型。您的问题是SFINAE的基础:您已定义了一个模板,该模板作为第二个和第三个参数T
,T
应该使用std::numeric_limits<T>::min
(和max
进行初始化)。现在,当编译器尝试确定要调用的函数时,它将找到该模板,使用T
表示int
(您提供的确切类型),0
表示min,然后尝试推断出最后一个论点。此时,它将通过替换T
中的已知模板参数,尝试通过默认模板参数获取std::numeric_limits<T>::max
值(最后一个模板参数)。问题是std::numeric_limits<int>::max
不是int
,而是静态成员函数,因此类型不匹配,导致替换失败。该语言确定替换失败不是错误( SFINAE ),它仅表示此模板将从函数调用的候选列表中删除。因为没有其他匹配的重载,编译器放弃并告诉您它无法找到该调用的匹配函数。
在C ++ 11中,您可以使用std::numeric_limits<T>::max()
,因为该函数被标记为const_expr
,因此可以调用来获取类型{{的常量表达式1}}可以用作模板参数,但如果您使用的是C ++ 03编译器,则需要以不同的方式解决问题,例如移动T
和{{1函数的默认参数,或提供从用户获取值的不同重载或将调用函数(如果参数不存在,则默认为min
,但后一选项更麻烦。
答案 3 :(得分:1)
模板函数使用参数类型进行实例化,param
为int&
。
宁可做
param = getInput(int(param));
min和max也不能是模板参数,模板参数是class,typename或POD。