为什么模板试图用'int&'而不是"int"进行实例化?

Why is the template trying to instanciate with 'int&' instead of 'int'?

本文关键字:int 实例化 为什么      更新时间:2023-10-16

我正在尝试编写一个简单的函数,该函数将从范围内的用户输入中获取一个数字。

在实例化此函数时,我明确告诉它我希望它与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(。

不要将模板用于minmax

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>

。使用最小/最大值作为值,当它们实际上是函数时。 也许这会混淆模板参数?

错误代码并不意味着您的想法。错误代码是以下各项的简写:

没有匹配的函数调用getInputint可修改的 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 编译器,则需要以不同的方式解决问题, 比如将minmax移动到函数的默认参数,或者提供不同的重载来从用户那里获取值或调用函数(如果参数不存在,则默认为 std::numeric_limist<T>::max,但后一个选项更麻烦。

模板函数是用参数类型实例化的,param是一个int&

而是做

 param = getInput(int(param));

此外,min和max不能是模板参数,模板参数是类,类型名或POD。