理解通用引用的类型推导
Understanding type deduction for universal references
设foo
为函数:
template< typename T >
void foo( T&& a ){}
以下 foo
的调用将 T
推导出什么类型:
foo( 0 ); // is T here int or int&& ?
int a = 0;
foo( a ); // is T here int or int& ?
类型推导的默认规则是引用类型永远不会是推导的结果。鉴于此代码,
template <class T>
void bar(T par);
bar(0);
int a;
bar(a);
int &b;
bar(b);
所有 3 个调用都会调用 foo<int>
。也就是说,T
被推导为 int
而 par
的类型为 int
.
转发引用通过简单添加一个规则来工作:当参数用于转发引用的类型推导时(即参数 T&&
用于 推导 T
)是X
类型的左值,使用X &
类型代替X
进行推导。
请注意,这意味着给定一个类型 X
,只有 X
或 X &
可以是类型推导的结果; X &&
永远不会。
让我们分析一下您的代码(我将重命名函数参数,以明确我指的是什么):
template <class T>
void foo(T &&par);
foo(0);
int a;
foo(a);
在第一种情况foo(0)
中,参数是类型int
的右值因此类型int
用于类型推导,意味着推导T
到int
(调用的函数是foo<int>
)并且par
的类型是int &&
.
在第二种情况 foo(a)
中,参数是类型 int
的 lvalue。转发引用规则生效,类型 int &
用于推导。 T
因此推导为int &
(调用的函数为foo<int&>
),par
的类型为“int & &&
”,折叠为int &
.
foo( 0 ); // is T here int or int&& ?
一个int
.
int a = 0;
foo( a ); // is T here int or int& ?
一个int&
.
推导上下文中的表达式T&&
,就像您提供的那样
template< typename T >
void foo( T&& a ){}
即T是根据提供的参数推导出来的,受制于
reference collapsing rules.
简而言之;
如果提供的参数是左值类型type
,T&&
将扩展为 type& &&
折叠为 type&
如果提供的参数是 rvalue 类型 type
,T&&
将扩展为 type &&
折叠为 type&&
注意两者都是references,如果需要触发右值
重载另一个函数,你需要做 std::forward<T>(a)
设foo
为函数:
template< typename T >
void foo( T&& a ){}
以下 foo
的调用将 T
推导出什么类型:
foo( 0 ); // is T here int or int&& ?
int a = 0;
foo( a ); // is T here int or int& ?
类型推导的默认规则是引用类型永远不会是推导的结果。鉴于此代码,
template <class T>
void bar(T par);
bar(0);
int a;
bar(a);
int &b;
bar(b);
所有 3 个调用都会调用 foo<int>
。也就是说,T
被推导为 int
而 par
的类型为 int
.
转发引用通过简单添加一个规则来工作:当参数用于转发引用的类型推导时(即参数 T&&
用于 推导 T
)是X
类型的左值,使用X &
类型代替X
进行推导。
请注意,这意味着给定一个类型 X
,只有 X
或 X &
可以是类型推导的结果; X &&
永远不会。
让我们分析一下您的代码(我将重命名函数参数,以明确我指的是什么):
template <class T>
void foo(T &&par);
foo(0);
int a;
foo(a);
在第一种情况foo(0)
中,参数是类型int
的右值因此类型int
用于类型推导,意味着推导T
到int
(调用的函数是foo<int>
)并且par
的类型是int &&
.
在第二种情况 foo(a)
中,参数是类型 int
的 lvalue。转发引用规则生效,类型 int &
用于推导。 T
因此推导为int &
(调用的函数为foo<int&>
),par
的类型为“int & &&
”,折叠为int &
.
foo( 0 ); // is T here int or int&& ?
一个int
.
int a = 0; foo( a ); // is T here int or int& ?
一个int&
.
推导上下文中的表达式T&&
,就像您提供的那样
template< typename T >
void foo( T&& a ){}
即T是根据提供的参数推导出来的,受制于 reference collapsing rules.
简而言之;
如果提供的参数是左值类型
type
,T&&
将扩展为type& &&
折叠为type&
如果提供的参数是 rvalue 类型
type
,T&&
将扩展为type &&
折叠为type&&
注意两者都是references,如果需要触发右值
重载另一个函数,你需要做 std::forward<T>(a)