模板函数在传入数字文字时遇到错误,但字符串文字没有

The template function encountered an error when passed in a numeric literal, but string literals didn't

我正在写这段代码

#include <iostream>
#include <string>


template <typename T>
void Print(T& value)
{
    std::cout << value << std::endl;
}

int main()
{
    Print("Hello");
    Print(1);
}

并且在编译时,编译器提示错误“void Print<int>(T &)' : cannot convert argument 1 from 'int' to 'T &'”。但是 Print("Hello") 没有得到错误。这是为什么?

然后我将 Print() 函数更改为

void Print(T value)
{
    std::cout << value << std::endl;
}

成功了。但是我不明白为什么以前的代码不起作用。

1 是一个 rvalue,因此不能绑定到 T&。不过,它 可以 绑定到 const T&

void Print(const T& value)

void Print(T&& value)

是修复。

案例一

这里我们考虑一下Print(1);是如何工作的。

在这种情况下,问题1 是一个 rvalue 而您正试图绑定该右值到对非常量 T(即 T&)的 左值引用,这是不可能的,因此是错误的。例如你不能有:

void Print(int &value)
{
    std::cout << value << std::endl;
}

int main()
{
   Print(1);// won't work
}

解决方案

所以要解决你的问题你可以使用左值引用const T(即const T&) 可以绑定到右值,如下所示:

template <typename T>
void Print(const T& value)//note the const added here
{
    std::cout << value << std::endl;
}
int main()
{
   
    Print(1); //works now
}

或者,您也可以将参数作为对非常量T(即T&&)的右值引用。

template <typename T>
void Print(T&& value)//note the && added here
{
    std::cout << value << std::endl;
}
int main()
{
   
    Print(1); //this works too
}

案例二

这里我们考虑语句Print("Hello");

在这种情况下,"Hello" 是一个 string literal,类型为 const char [6]。此外,字符串文字 "Hello" 是一个 lvalue.

而且我们知道我们可以将左值绑定到 对非常量 T(即 T&)的左值引用。所以在这种情况下没有错误。另请注意,在这种情况下,T 被推断为 const char [6].

备注

在上面的情况 2 (Print("Hello");) 中,没有类型衰减,因为参数是通过引用而不是值传递的。

因为这个:

test.cpp:45:11: error: cannot bind non-const lvalue reference of type 'int&' to an rvalue of type 'int'
   45 |     Print(1);
      |           ^

因此将其转换为通用参考:

template <typename T>
void Print( T&& value ) // notice &&, that's a universal reference, not an rvalue ref
{
    std::cout << value << std::endl;
}