首页 > 解决方案 > 为什么这个类模板参数被视为转发引用?

问题描述

根据https://en.cppreference.com/w/cpp/language/reference,转发引用是,

  1. 声明为右值引用的函数模板的函数参数。
  2. 汽车&&。

https://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers Scott Meyers 解释说,虽然 vector::push_back(T&& x) 需要一个 T&&,但它不是通用的参考。这只是一个普通的右值引用。

但是,我下面的代码编译并运行良好:

#include <iostream>

template<typename T>
class MyClass
{
public:
    void f(T&& x)
    {
        std::cout << __FUNCSIG__ << std::endl;
    }
};

int main()
{
    int i = 10;

    MyClass<int&> myClass1;
    myClass1.f(i); //void __thiscall MyClass<int &>::f(int &)

    MyClass<int&&> myClass2;
    myClass2.f(10); //void __thiscall MyClass<int &&>::f(int &&)
}

听起来 T&& 在这里被视为转发引用,因为 f(T&& x) 接受左值和右值引用。但是 f(T&& x) 是类模板成员;它不是一个独立的函数模板。这是否违反我上面提到的转发参考定义?

<<\添加-->

在函数模板中转发引用的情况下,函数模板本身也需要基于特定类型 T 进行实例化。我们可以显式地表达这一点:

template<class T>
void f(T&& x)
{}

int main() {
    int i = 10;
    f<int&>(i); // argument is lvalue
    f<int&&>(10); // argument is rvalue
}

f<\int&> 和 f<\int&&> 是上述函数模板的两个不同实例。它们也不是在幕后指向相同的函数地址,类似于类模板实例化。当然,我们需要类对象来使用它的功能。

<--结束添加>

标签: c++rvalue-referencetype-deductionforwarding-reference

解决方案


因为f(T&& x)接受左值和右值引用

它没有。您在这里没有比较相同的成员函数。MyClass<int&>::f是一个只接受左值的类的成员函数。同时MyClass<int&&>::f另一个类的成员函数,它只接受右值。

类模板不是类。这是一个千篇一律的制作类的工具。尽管特化具有类似命名的成员函数,但它们仍然是不同类中的不同函数。

如果您尝试传递MyClass<int&>::f右值,您的代码将无法成功构建,

myClass1.f(10); // ERROR

引用折叠使生成f的 ' 接受不同值类别的引用,但是一旦类被实例化,该成员将只接受特定的值类别。它不像转发引用那样转发在调用站点推导出的值类别。


推荐阅读