#for example:
#1:
template <typename T>
void func(T &) {}
int a;
const int b;
func(a); // T -> int
func(b); // T -> const int
func(5); // wrong. 5 is a right value
#2:
template <typename T>
void func(const T &) {}
int a;
const int b;
func(a); // T -> int
func(b); // T -> int
func(5); // T -> int
#3
template <typename T>
void func(T &&) {}
func(5); // T -> int
我的问题是:
为什么第一个代码不起作用,为什么这与左/右值有关;
为什么第三行的T
不是const int
答案 0 :(得分:1)
为什么第一个代码不起作用;为什么这与左/右值有关;
对于第一种情况,T
将推导为int
,则参数类型为int &
,这是对非常量的左值引用。并且5
是一个右值,它不能绑定到对非const的左值引用,然后调用失败。
对于第二种情况,函数的参数类型为const int &
,即const的左值引用,可以像5
那样绑定到右值。
如果参数不是为什么第三行的
T
不是const int
const
类型,则模板参数推导将不会 add const
。 5
的类型为int
(这是一个右值),但其类型不是const int
。
另一方面,我们有forwarding reference用于处理左值/右值。例如
template <typename T>
void func(T &&) {}
int a;
const int b;
func(a); // T -> int&; parameter type -> int&
func(b); // T -> const int&; parameter type -> const int&
func(5); // Fine. T -> int; paramter type -> int&&
答案 1 :(得分:0)
所有这些都取决于表达式的属性。 5
是一个表达式。它具有类型和值类别。 5
的类型是int
,而不是const int
,而只是普通的int
。这是一个prvalue(这是值类别)。
因此,根据T&
推论5
时,只能推导类型为int
。这意味着合成函数接受int&
,它不能绑定到右值。
在推论T const&
时,根据模板参数推论中的适当规定,类型T
仍只能推论为int
。但是现在合成函数接受int const&
,并且可以绑定到右值。