使用通用引用时键入扣除

时间:2016-11-11 19:05:45

标签: c++ c++14 rvalue-reference lvalue type-deduction

有人可以帮助我理解为什么输出以下代码

template< typename T >
void check()
{
  std::cout << "unknow type" << std::endl;
}

template<>
void check<int>()
{
  std::cout << "int" << std::endl;
}

template<>
void check<int&>()
{
  std::cout << "int&" << std::endl;
}

template<>
void check<int&&>()
{
  std::cout << "int&&" << std::endl;
}

template< typename T >
void bar( T&& a )
{
  check<T>();
}

int main()
{
  bar(0);

  int a = 0;
  bar( a );
}

int
int&

而不是

int&&
int&

从我的观点来看,似乎更直观的是,r值引用保留为r值引用,l值引用保留为l值引用,但似乎只有l值引用仍为l值引用和r值变为非参考值。 这背后的动机/想法是什么?

1 个答案:

答案 0 :(得分:4)

bar(0);调用专精bar<int>(int&&),即T被推断为int,因此check<T>()check<int>()。参数类型为T&& int&&,但这是参数的类型,而不是T类型。

这与非转发引用完全一致。如果你定义:

template<typename T> void baz(T&);

并且您使用int类型的左值调用它,然后T推断为int,而不是int&

关于转发引用(例如您的示例用途)的唯一特殊之处在于,对于T&&,可以将类型推导为左值引用,将其称为R,在这种情况下参数类型为R&&,与add_rvalue_reference_t<R>相同,仅为R。因此,对于致电bar(a),您调用专业化bar<int&>(int&),即T被推断为int&

当您使用显式模板参数列表调用bar<int&&>(0)时,没有参数推断,因此Tint&&替换,因此参数类型T&&为{ {1}}只是add_rvalue_reference_t<int&&>