7

foo函数:

template< typename T >
void foo( T&& a ){}

T以下调用将推导出什么类型foo

foo( 0 ); // is T here int or int&& ?

int a = 0;
foo( a ); // is T here int or int& ?
4

3 回答 3

9

类型推导的默认规则是引用类型永远不能是推导的结果。鉴于此代码,

template <class T>
void bar(T par);

bar(0);
int a;
bar(a);
int &b;
bar(b);

所有 3 个电话都会打电话foo<int>。即,T推导为int并且par属于 类型int

转发引用通过简单添加一条规则来工作:当用于转发引用(即deduced的参数)T&&的类型推导的参数是 type 的左值时,使用该类型而不是推导。 TXX &X

请注意,这意味着给定一个 type X,只有X或者X &可以是类型推导的结果;X &&永远不能。

让我们分析您的代码(我将重命名他的函数参数,以明确我所指的内容):

template <class T>
void foo(T &&par);

foo(0);

int a;
foo(a);

在第一种情况下foo(0),参数是类型的右值因此int类型int用于类型推导,这意味着T推导到int(称为 is 的函数foo<int>)和类型parint &&

在第二种情况下foo(a),参数是类型的左值int。转发参考规则启动,类型int &用于扣除。T因此推导为int &(函数称为 is foo<int&>),类型par为 " int & &&",可折叠为int &

于 2017-10-04T08:27:35.480 回答
2

推断上下文中的表达式T&&,例如您提供的内容

template< typename T >
void foo( T&& a ){}

即 T 是根据提供的参数推导出来的,受 参考折叠规则的约束。

简而言之;

  • 如果提供的参数是type的左值typeT&& 将展开为type& &&折叠为type&

  • 如果提供的参数是type的右值typeT&& 将扩展为type &&折叠为type&&

注意两者都是引用,如果需要触发另一个函数的右值重载,需要做std::forward<T>(a)

于 2017-10-04T08:38:13.933 回答
1

富(0);// 这里的 T 是 int 还是 int&& ?

一个int

整数a = 0;富(一);// 这里的 T 是 int 还是 int& ?

一个int&

于 2017-10-04T08:28:45.217 回答