为什么模板试图用'int&'而不是"int"进行实例化?
Why is the template trying to instanciate with 'int&' instead of 'int'?
我正在尝试编写一个简单的函数,该函数将从范围内的用户输入中获取一个数字。
在实例化此函数时,我明确告诉它我希望它与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&'?
}
更新
如果我尝试查尔斯B建议:
void get(const std::string& prompt, int& param){
cout << prompt << " [" << param << "]:";
param = getInput<int,0>(int(param));
}
我得到
thermo.cpp:105:36:错误:调用"getInput(int("没有匹配函数
忘记:
G++ 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
(。
不要将模板用于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 在编译过程中是已知的。
这是否是问题所在,但我无法想象它有帮助。 这一行:
template<class T, T min = std::numeric_limits<T>::min, T max = std::numeric_limits<T>::max>
。使用最小/最大值作为值,当它们实际上是函数时。 也许这会混淆模板参数?
错误代码并不意味着您的想法。错误代码是以下各项的简写:
没有匹配的函数调用getInput
将int
可修改的 lvalue 表达式作为单个参数
其中int
可修改的左值表达式是在本例中用于调用的表达式的类型 param
.现在的问题是,这种格式的错误代码的输出非常冗长,并且仅使用两三个非平凡类型的参数就很难阅读,因此编译器压缩了错误报告并告诉您:
没有匹配的函数调用getInput(int&)
,请注意,这里的int&
不是将要调用的函数的类型,因为编译器无法找到这样的函数,而是调用中使用的参数的类型。
如果您执行 CharlesB 建议的更改,则会收到一条不同的错误消息,指出它找不到getInput(int)
。这里的区别在于int(param)
创建一个临时(右值表达式(,因此错误现在反映了它。需要不同的错误代码是因为如果您有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
,因此可以调用该函数来获取可用作模板参数的 T
类型的常量表达式,但是如果您使用的是 C++03 编译器,则需要以不同的方式解决问题, 比如将min
和max
移动到函数的默认参数,或者提供不同的重载来从用户那里获取值或调用函数(如果参数不存在,则默认为 std::numeric_limist<T>::max
,但后一个选项更麻烦。
模板函数是用参数类型实例化的,param
是一个int&
。
而是做
param = getInput(int(param));
此外,min和max不能是模板参数,模板参数是类,类型名或POD。
- 从C++实例化QML
- 设计一个只能由特定类实例化的类(如果可能的话,通过make_unique)
- 如何创建一个空的全局类并在启动时实例化它
- 在两个类中共享相同的函数调用,并在不需要时避免空实例化
- 约束和显式模板实例化
- 为什么包含windows.h会产生语法错误,从而阻止类的实例化?(C2146,C2065)
- 对象实例化调用构造函数的次数太多
- 如何使用非默认构造函数实例化模板化类
- 静态数据成员模板专用化的实例化点在哪里
- 错误的cv::face FacemarkLBF实例化
- 未定义模板'std::__1::function<int (double, double, double, double)>'的隐式实例化
- c++模板实例化可以使用int、long等,但不能使用float、double等
- 当我创建一个int指针并实例化一个数组时,数组在内存中发生了什么
- 使用向量<向量>成员实例化对象时的隔离错误<int>
- int&& 在模板实例化中有效吗?
- 避免使用int参数的模板类的C++爆炸性实例化
- 如何实例化 int 类型的数组对象并在 c++ 中填充它
- 为什么模板试图用'int&'而不是"int"进行实例化?
- 未定义模板 'std::__1::array<int, 3>' 的隐式实例化
- 基于数据实例化int模板