为什么在这种情况下模板参数是引用?

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);
}

它打印 010100,意思是 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*&&。)