为什么在这种情况下模板参数是引用?
Why is template parameter a reference in this case?
在玩 std::forward 时偶然发现了一个奇怪的行为。这是一个小例子:
#include <type_traits>
#include <iostream>
template <typename A>
void func(A&&)
{
std::cout
<< std::is_pointer<A>::value
<< std::is_lvalue_reference<A>::value
<< std::is_rvalue_reference<A>::value
<< std::endl;
using B = typename std::remove_reference<A>::type;
std::cout
<< std::is_pointer<B>::value
<< std::is_lvalue_reference<B>::value
<< std::is_rvalue_reference<B>::value
<< std::endl;
}
int main()
{
int* p = nullptr;
func(p);
}
它打印 010
和 100
,意思是 A
是引用而不是指针,而 std::remove_reference<A>
是预期的指针。
但为什么会这样呢?我认为 A
将是一个指针,而 A&&
将是函数体内的一个引用。另外,如果是这种情况,A&
和A&&
是什么类型?
这就是 forwarding reference 的工作方式;当传递左值时,模板参数 A
将被推断为 lvalue-reference。对于这种情况,它是 int*&
,即指向指针的 lvalue-reference。 (引用折叠后,函数参数的类型也将是 int*&
。)
当传递一个右值时,A
将被推断为 non-reference 类型。例如,如果您传递类型为 int*
的右值,A
将被推断为 int*
。 (那么函数参数的类型将是 int*&&
。)
在玩 std::forward 时偶然发现了一个奇怪的行为。这是一个小例子:
#include <type_traits>
#include <iostream>
template <typename A>
void func(A&&)
{
std::cout
<< std::is_pointer<A>::value
<< std::is_lvalue_reference<A>::value
<< std::is_rvalue_reference<A>::value
<< std::endl;
using B = typename std::remove_reference<A>::type;
std::cout
<< std::is_pointer<B>::value
<< std::is_lvalue_reference<B>::value
<< std::is_rvalue_reference<B>::value
<< std::endl;
}
int main()
{
int* p = nullptr;
func(p);
}
它打印 010
和 100
,意思是 A
是引用而不是指针,而 std::remove_reference<A>
是预期的指针。
但为什么会这样呢?我认为 A
将是一个指针,而 A&&
将是函数体内的一个引用。另外,如果是这种情况,A&
和A&&
是什么类型?
这就是 forwarding reference 的工作方式;当传递左值时,模板参数 A
将被推断为 lvalue-reference。对于这种情况,它是 int*&
,即指向指针的 lvalue-reference。 (引用折叠后,函数参数的类型也将是 int*&
。)
当传递一个右值时,A
将被推断为 non-reference 类型。例如,如果您传递类型为 int*
的右值,A
将被推断为 int*
。 (那么函数参数的类型将是 int*&&
。)